1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.providers.anonymous;
17
18 import org.acegisecurity.Authentication;
19 import org.acegisecurity.context.SecurityContextHolder;
20 import org.acegisecurity.userdetails.memory.UserAttribute;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 import org.springframework.beans.factory.InitializingBean;
26
27 import org.springframework.util.Assert;
28
29 import java.io.IOException;
30
31 import javax.servlet.Filter;
32 import javax.servlet.FilterChain;
33 import javax.servlet.FilterConfig;
34 import javax.servlet.ServletException;
35 import javax.servlet.ServletRequest;
36 import javax.servlet.ServletResponse;
37
38
39 /***
40 * Detects if there is no <code>Authentication</code> object in the
41 * <code>SecurityContextHolder</code>, and populates it with one if needed.
42 *
43 * <p>
44 * <b>Do not use this class directly.</b> Instead configure
45 * <code>web.xml</code> to use the {@link
46 * org.acegisecurity.util.FilterToBeanProxy}.
47 * </p>
48 *
49 * @author Ben Alex
50 * @version $Id: AnonymousProcessingFilter.java,v 1.9 2005/11/29 13:10:13 benalex Exp $
51 */
52 public class AnonymousProcessingFilter implements Filter, InitializingBean {
53
54
55 private static final Log logger = LogFactory.getLog(AnonymousProcessingFilter.class);
56
57
58
59 private String key;
60 private UserAttribute userAttribute;
61 private boolean removeAfterRequest = true;
62
63
64
65 public void setKey(String key) {
66 this.key = key;
67 }
68
69 public String getKey() {
70 return key;
71 }
72
73 /***
74 * Controls whether the filter will remove the Anonymous token after the
75 * request is complete. Generally this is desired to avoid the expense of
76 * a session being created by {@link
77 * org.acegisecurity.context.HttpSessionContextIntegrationFilter
78 * HttpSessionContextIntegrationFilter} simply to store the Anonymous
79 * authentication token.
80 *
81 * <p>
82 * Defaults to <code>true</code>, being the most optimal and appropriate
83 * option (ie <code>AnonymousProcessingFilter</code> will clear the token
84 * at the end of each request, thus avoiding the session creation overhead
85 * in a typical configuration.
86 * </p>
87 *
88 * @param removeAfterRequest DOCUMENT ME!
89 */
90 public void setRemoveAfterRequest(boolean removeAfterRequest) {
91 this.removeAfterRequest = removeAfterRequest;
92 }
93
94 public boolean isRemoveAfterRequest() {
95 return removeAfterRequest;
96 }
97
98 public void setUserAttribute(UserAttribute userAttributeDefinition) {
99 this.userAttribute = userAttributeDefinition;
100 }
101
102 public UserAttribute getUserAttribute() {
103 return userAttribute;
104 }
105
106 public void afterPropertiesSet() throws Exception {
107 Assert.notNull(userAttribute);
108 Assert.hasLength(key);
109 }
110
111 /***
112 * Does nothing - we reply on IoC lifecycle services instead.
113 */
114 public void destroy() {}
115
116 public void doFilter(ServletRequest request, ServletResponse response,
117 FilterChain chain) throws IOException, ServletException {
118 boolean addedToken = false;
119
120 if (applyAnonymousForThisRequest(request)) {
121 if (SecurityContextHolder.getContext().getAuthentication() == null) {
122 SecurityContextHolder.getContext().setAuthentication(createAuthentication(
123 request));
124 addedToken = true;
125
126 if (logger.isDebugEnabled()) {
127 logger.debug(
128 "Populated SecurityContextHolder with anonymous token: '"
129 + SecurityContextHolder.getContext().getAuthentication()
130 + "'");
131 }
132 } else {
133 if (logger.isDebugEnabled()) {
134 logger.debug(
135 "SecurityContextHolder not populated with anonymous token, as it already contained: '"
136 + SecurityContextHolder.getContext().getAuthentication()
137 + "'");
138 }
139 }
140 }
141
142 try {
143 chain.doFilter(request, response);
144 } finally {
145 if (addedToken && removeAfterRequest
146 && createAuthentication(request).equals(SecurityContextHolder.getContext()
147 .getAuthentication())) {
148 SecurityContextHolder.getContext().setAuthentication(null);
149 }
150 }
151 }
152
153 /***
154 * Does nothing - we reply on IoC lifecycle services instead.
155 *
156 * @param ignored not used
157 *
158 * @throws ServletException DOCUMENT ME!
159 */
160 public void init(FilterConfig ignored) throws ServletException {}
161
162 /***
163 * Enables subclasses to determine whether or not an anonymous
164 * authentication token should be setup for this request. This is useful
165 * if anonymous authentication should be allowed only for specific IP
166 * subnet ranges etc.
167 *
168 * @param request to assist the method determine request details
169 *
170 * @return <code>true</code> if the anonymous token should be setup for
171 * this request (provided that the request doesn't already have
172 * some other <code>Authentication</code> inside it), or
173 * <code>false</code> if no anonymous token should be setup for
174 * this request
175 */
176 protected boolean applyAnonymousForThisRequest(ServletRequest request) {
177 return true;
178 }
179
180 protected Authentication createAuthentication(ServletRequest request) {
181 return new AnonymousAuthenticationToken(key,
182 userAttribute.getPassword(), userAttribute.getAuthorities());
183 }
184 }