View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.cas;
20  
21  import org.apache.shiro.authc.AuthenticationException;
22  import org.apache.shiro.authc.AuthenticationToken;
23  import org.apache.shiro.subject.Subject;
24  import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
25  import org.apache.shiro.web.util.WebUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import javax.servlet.ServletRequest;
30  import javax.servlet.ServletResponse;
31  import javax.servlet.http.HttpServletRequest;
32  import java.io.IOException;
33  
34  /**
35   * This filter validates the CAS service ticket to authenticate the user.  It must be configured on the URL recognized
36   * by the CAS server.  For example, in {@code shiro.ini}:
37   * <pre>
38   * [main]
39   * casFilter = org.apache.shiro.cas.CasFilter
40   * ...
41   *
42   * [urls]
43   * /shiro-cas = casFilter
44   * ...
45   * </pre>
46   * (example : http://host:port/mycontextpath/shiro-cas)
47   *
48   * @since 1.2
49   */
50  public class CasFilter extends AuthenticatingFilter {
51      
52      private static Logger logger = LoggerFactory.getLogger(CasFilter.class);
53      
54      // the name of the parameter service ticket in url
55      private static final String TICKET_PARAMETER = "ticket";
56      
57      // the url where the application is redirected if the CAS service ticket validation failed (example : /mycontextpatch/cas_error.jsp)
58      private String failureUrl;
59      
60      /**
61       * The token created for this authentication is a CasToken containing the CAS service ticket received on the CAS service url (on which
62       * the filter must be configured).
63       * 
64       * @param request the incoming request
65       * @param response the outgoing response
66       * @throws Exception if there is an error processing the request.
67       */
68      @Override
69      protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
70          HttpServletRequest httpRequest = (HttpServletRequest) request;
71          String ticket = httpRequest.getParameter(TICKET_PARAMETER);
72          return new CasToken(ticket);
73      }
74      
75      /**
76       * Execute login by creating {@link #createToken(javax.servlet.ServletRequest, javax.servlet.ServletResponse) token} and logging subject
77       * with this token.
78       * 
79       * @param request the incoming request
80       * @param response the outgoing response
81       * @throws Exception if there is an error processing the request.
82       */
83      @Override
84      protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
85          return executeLogin(request, response);
86      }
87      
88      /**
89       * Returns <code>false</code> to always force authentication (user is never considered authenticated by this filter).
90       * 
91       * @param request the incoming request
92       * @param response the outgoing response
93       * @param mappedValue the filter-specific config value mapped to this filter in the URL rules mappings.
94       * @return <code>false</code>
95       */
96      @Override
97      protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
98          return false;
99      }
100     
101     /**
102      * If login has been successful, redirect user to the original protected url.
103      * 
104      * @param token the token representing the current authentication
105      * @param subject the current authenticated subjet
106      * @param request the incoming request
107      * @param response the outgoing response
108      * @throws Exception if there is an error processing the request.
109      */
110     @Override
111     protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
112                                      ServletResponse response) throws Exception {
113         issueSuccessRedirect(request, response);
114         return false;
115     }
116     
117     /**
118      * If login has failed, redirect user to the CAS error page (no ticket or ticket validation failed) except if the user is already
119      * authenticated, in which case redirect to the default success url.
120      * 
121      * @param token the token representing the current authentication
122      * @param ae the current authentication exception
123      * @param request the incoming request
124      * @param response the outgoing response
125      */
126     @Override
127     protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException ae, ServletRequest request,
128                                      ServletResponse response) {
129         // is user authenticated or in remember me mode ?
130         Subject subject = getSubject(request, response);
131         if (subject.isAuthenticated() || subject.isRemembered()) {
132             try {
133                 issueSuccessRedirect(request, response);
134             } catch (Exception e) {
135                 logger.error("Cannot redirect to the default success url", e);
136             }
137         } else {
138             try {
139                 WebUtils.issueRedirect(request, response, failureUrl);
140             } catch (IOException e) {
141                 logger.error("Cannot redirect to failure url : {}", failureUrl, e);
142             }
143         }
144         return false;
145     }
146     
147     public void setFailureUrl(String failureUrl) {
148         this.failureUrl = failureUrl;
149     }
150 }