Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AuthenticatingFilter |
|
| 2.090909090909091;2.091 |
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.web.filter.authc; | |
20 | ||
21 | import org.apache.shiro.authc.AuthenticationException; | |
22 | import org.apache.shiro.authc.AuthenticationToken; | |
23 | import org.apache.shiro.authc.UsernamePasswordToken; | |
24 | import org.apache.shiro.authz.UnauthenticatedException; | |
25 | import org.apache.shiro.subject.Subject; | |
26 | ||
27 | import javax.servlet.ServletException; | |
28 | import javax.servlet.ServletRequest; | |
29 | import javax.servlet.ServletResponse; | |
30 | import java.io.IOException; | |
31 | import java.util.Arrays; | |
32 | ||
33 | /** | |
34 | * An <code>AuthenticationFilter</code> that is capable of automatically performing an authentication attempt | |
35 | * based on the incoming request. | |
36 | * | |
37 | * @since 0.9 | |
38 | */ | |
39 | 101 | public abstract class AuthenticatingFilter extends AuthenticationFilter { |
40 | public static final String PERMISSIVE = "permissive"; | |
41 | ||
42 | //TODO - complete JavaDoc | |
43 | ||
44 | protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { | |
45 | 0 | AuthenticationToken token = createToken(request, response); |
46 | 0 | if (token == null) { |
47 | 0 | String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " + |
48 | "must be created in order to execute a login attempt."; | |
49 | 0 | throw new IllegalStateException(msg); |
50 | } | |
51 | try { | |
52 | 0 | Subject subject = getSubject(request, response); |
53 | 0 | subject.login(token); |
54 | 0 | return onLoginSuccess(token, subject, request, response); |
55 | 0 | } catch (AuthenticationException e) { |
56 | 0 | return onLoginFailure(token, e, request, response); |
57 | } | |
58 | } | |
59 | ||
60 | protected abstract AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception; | |
61 | ||
62 | protected AuthenticationToken createToken(String username, String password, | |
63 | ServletRequest request, ServletResponse response) { | |
64 | 4 | boolean rememberMe = isRememberMe(request); |
65 | 4 | String host = getHost(request); |
66 | 4 | return createToken(username, password, rememberMe, host); |
67 | } | |
68 | ||
69 | protected AuthenticationToken createToken(String username, String password, | |
70 | boolean rememberMe, String host) { | |
71 | 4 | return new UsernamePasswordToken(username, password, rememberMe, host); |
72 | } | |
73 | ||
74 | protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, | |
75 | ServletRequest request, ServletResponse response) throws Exception { | |
76 | 0 | return true; |
77 | } | |
78 | ||
79 | protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, | |
80 | ServletRequest request, ServletResponse response) { | |
81 | 0 | return false; |
82 | } | |
83 | ||
84 | /** | |
85 | * Returns the host name or IP associated with the current subject. This method is primarily provided for use | |
86 | * during construction of an <code>AuthenticationToken</code>. | |
87 | * <p/> | |
88 | * The default implementation merely returns {@link ServletRequest#getRemoteHost()}. | |
89 | * | |
90 | * @param request the incoming ServletRequest | |
91 | * @return the <code>InetAddress</code> to associate with the login attempt. | |
92 | */ | |
93 | protected String getHost(ServletRequest request) { | |
94 | 4 | return request.getRemoteHost(); |
95 | } | |
96 | ||
97 | /** | |
98 | * Returns <code>true</code> if "rememberMe" should be enabled for the login attempt associated with the | |
99 | * current <code>request</code>, <code>false</code> otherwise. | |
100 | * <p/> | |
101 | * This implementation always returns <code>false</code> and is provided as a template hook to subclasses that | |
102 | * support <code>rememberMe</code> logins and wish to determine <code>rememberMe</code> in a custom mannner | |
103 | * based on the current <code>request</code>. | |
104 | * | |
105 | * @param request the incoming ServletRequest | |
106 | * @return <code>true</code> if "rememberMe" should be enabled for the login attempt associated with the | |
107 | * current <code>request</code>, <code>false</code> otherwise. | |
108 | */ | |
109 | protected boolean isRememberMe(ServletRequest request) { | |
110 | 4 | return false; |
111 | } | |
112 | ||
113 | /** | |
114 | * Determines whether the current subject should be allowed to make the current request. | |
115 | * <p/> | |
116 | * The default implementation returns <code>true</code> if the user is authenticated. Will also return | |
117 | * <code>true</code> if the {@link #isLoginRequest} returns false and the "permissive" flag is set. | |
118 | * | |
119 | * @return <code>true</code> if request should be allowed access | |
120 | */ | |
121 | @Override | |
122 | protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { | |
123 | 0 | return super.isAccessAllowed(request, response, mappedValue) || |
124 | (!isLoginRequest(request, response) && isPermissive(mappedValue)); | |
125 | } | |
126 | ||
127 | /** | |
128 | * Returns <code>true</code> if the mappedValue contains the {@link #PERMISSIVE} qualifier. | |
129 | * | |
130 | * @return <code>true</code> if this filter should be permissive | |
131 | */ | |
132 | protected boolean isPermissive(Object mappedValue) { | |
133 | 0 | if(mappedValue != null) { |
134 | 0 | String[] values = (String[]) mappedValue; |
135 | 0 | return Arrays.binarySearch(values, PERMISSIVE) >= 0; |
136 | } | |
137 | 0 | return false; |
138 | } | |
139 | ||
140 | /** | |
141 | * Overrides the default behavior to call {@link #onAccessDenied} and swallow the exception if the exception is | |
142 | * {@link UnauthenticatedException}. | |
143 | */ | |
144 | @Override | |
145 | protected void cleanup(ServletRequest request, ServletResponse response, Exception existing) throws ServletException, IOException { | |
146 | 0 | if (existing instanceof UnauthenticatedException || (existing instanceof ServletException && existing.getCause() instanceof UnauthenticatedException)) |
147 | { | |
148 | try { | |
149 | 0 | onAccessDenied(request, response); |
150 | 0 | existing = null; |
151 | 0 | } catch (Exception e) { |
152 | 0 | existing = e; |
153 | 0 | } |
154 | } | |
155 | 0 | super.cleanup(request, response, existing); |
156 | ||
157 | 0 | } |
158 | } |