1
0
mirror of synced 2026-08-04 01:07:02 +00:00

SEC-168: Prevent errors with concurrent session support.

This commit is contained in:
Ben Alex
2006-02-08 04:42:03 +00:00
parent 7883aefa16
commit 9d213f46a4
2 changed files with 124 additions and 95 deletions
@@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,8 @@
package org.acegisecurity.providers.anonymous;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.providers.AbstractAuthenticationToken;
import org.springframework.util.Assert;
import org.acegisecurity.providers.AbstractAuthenticationToken;
import java.io.Serializable;
@@ -33,6 +32,7 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken
implements Serializable {
//~ Instance fields ========================================================
private Object details;
private Object principal;
private boolean authenticated;
private int keyHash;
@@ -50,7 +50,6 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken
*/
public AnonymousAuthenticationToken(String key, Object principal,
GrantedAuthority[] authorities) {
super(authorities);
if ((key == null) || ("".equals(key)) || (principal == null)
@@ -62,36 +61,11 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken
this.keyHash = key.hashCode();
this.principal = principal;
this.authenticated = true;
this.authenticated = true;
}
//~ Methods ================================================================
public void setAuthenticated(boolean isAuthenticated) {
this.authenticated = isAuthenticated;
}
public boolean isAuthenticated() {
return this.authenticated;
}
/**
* Always returns an empty <code>String</code>
*
* @return an empty String
*/
public Object getCredentials() {
return "";
}
public int getKeyHash() {
return this.keyHash;
}
public Object getPrincipal() {
return this.principal;
}
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
@@ -104,9 +78,50 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken
return false;
}
return true;
if ((this.details == null) && (test.getDetails() != null)) {
return false;
}
if ((this.details != null) && (test.getDetails() == null)) {
return false;
}
return this.details.equals(test.getDetails());
}
return false;
}
/**
* Always returns an empty <code>String</code>
*
* @return an empty String
*/
public Object getCredentials() {
return "";
}
public Object getDetails() {
return details;
}
public int getKeyHash() {
return this.keyHash;
}
public Object getPrincipal() {
return this.principal;
}
public boolean isAuthenticated() {
return this.authenticated;
}
public void setAuthenticated(boolean isAuthenticated) {
this.authenticated = isAuthenticated;
}
public void setDetails(Object details) {
this.details = details;
}
}
@@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,11 @@
package org.acegisecurity.providers.anonymous;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.acegisecurity.userdetails.memory.UserAttribute;
import org.apache.commons.logging.Log;
@@ -34,6 +38,7 @@ import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
@@ -62,52 +67,41 @@ public class AnonymousProcessingFilter implements Filter, InitializingBean {
//~ Methods ================================================================
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
/**
* Controls whether the filter will remove the Anonymous token after the
* request is complete. Generally this is desired to avoid the expense of
* a session being created by {@link
* org.acegisecurity.context.HttpSessionContextIntegrationFilter
* HttpSessionContextIntegrationFilter} simply to store the Anonymous
* authentication token.
*
* <p>
* Defaults to <code>true</code>, being the most optimal and appropriate
* option (ie <code>AnonymousProcessingFilter</code> will clear the token
* at the end of each request, thus avoiding the session creation overhead
* in a typical configuration.
* </p>
*
* @param removeAfterRequest DOCUMENT ME!
*/
public void setRemoveAfterRequest(boolean removeAfterRequest) {
this.removeAfterRequest = removeAfterRequest;
}
public boolean isRemoveAfterRequest() {
return removeAfterRequest;
}
public void setUserAttribute(UserAttribute userAttributeDefinition) {
this.userAttribute = userAttributeDefinition;
}
public UserAttribute getUserAttribute() {
return userAttribute;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(userAttribute);
Assert.hasLength(key);
}
/**
* Enables subclasses to determine whether or not an anonymous
* authentication token should be setup for this request. This is useful
* if anonymous authentication should be allowed only for specific IP
* subnet ranges etc.
*
* @param request to assist the method determine request details
*
* @return <code>true</code> if the anonymous token should be setup for
* this request (provided that the request doesn't already have
* some other <code>Authentication</code> inside it), or
* <code>false</code> if no anonymous token should be setup for
* this request
*/
protected boolean applyAnonymousForThisRequest(ServletRequest request) {
return true;
}
protected Authentication createAuthentication(ServletRequest request) {
Assert.isInstanceOf(HttpServletRequest.class, request,
"ServletRequest must be an instance of HttpServletRequest");
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key,
userAttribute.getPassword(), userAttribute.getAuthorities());
auth.setDetails(new WebAuthenticationDetails(
(HttpServletRequest) request));
return auth;
}
/**
* Does nothing - we reply on IoC lifecycle services instead.
*/
@@ -119,7 +113,8 @@ public class AnonymousProcessingFilter implements Filter, InitializingBean {
if (applyAnonymousForThisRequest(request)) {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(createAuthentication(
SecurityContextHolder.getContext()
.setAuthentication(createAuthentication(
request));
addedToken = true;
@@ -143,13 +138,22 @@ public class AnonymousProcessingFilter implements Filter, InitializingBean {
chain.doFilter(request, response);
} finally {
if (addedToken && removeAfterRequest
&& createAuthentication(request).equals(SecurityContextHolder.getContext()
.getAuthentication())) {
&& createAuthentication(request)
.equals(SecurityContextHolder.getContext()
.getAuthentication())) {
SecurityContextHolder.getContext().setAuthentication(null);
}
}
}
public String getKey() {
return key;
}
public UserAttribute getUserAttribute() {
return userAttribute;
}
/**
* Does nothing - we reply on IoC lifecycle services instead.
*
@@ -159,26 +163,36 @@ public class AnonymousProcessingFilter implements Filter, InitializingBean {
*/
public void init(FilterConfig ignored) throws ServletException {}
/**
* Enables subclasses to determine whether or not an anonymous
* authentication token should be setup for this request. This is useful
* if anonymous authentication should be allowed only for specific IP
* subnet ranges etc.
*
* @param request to assist the method determine request details
*
* @return <code>true</code> if the anonymous token should be setup for
* this request (provided that the request doesn't already have
* some other <code>Authentication</code> inside it), or
* <code>false</code> if no anonymous token should be setup for
* this request
*/
protected boolean applyAnonymousForThisRequest(ServletRequest request) {
return true;
public boolean isRemoveAfterRequest() {
return removeAfterRequest;
}
protected Authentication createAuthentication(ServletRequest request) {
return new AnonymousAuthenticationToken(key,
userAttribute.getPassword(), userAttribute.getAuthorities());
public void setKey(String key) {
this.key = key;
}
/**
* Controls whether the filter will remove the Anonymous token after the
* request is complete. Generally this is desired to avoid the expense of
* a session being created by {@link
* org.acegisecurity.context.HttpSessionContextIntegrationFilter
* HttpSessionContextIntegrationFilter} simply to store the Anonymous
* authentication token.
*
* <p>
* Defaults to <code>true</code>, being the most optimal and appropriate
* option (ie <code>AnonymousProcessingFilter</code> will clear the token
* at the end of each request, thus avoiding the session creation overhead
* in a typical configuration.
* </p>
*
* @param removeAfterRequest DOCUMENT ME!
*/
public void setRemoveAfterRequest(boolean removeAfterRequest) {
this.removeAfterRequest = removeAfterRequest;
}
public void setUserAttribute(UserAttribute userAttributeDefinition) {
this.userAttribute = userAttributeDefinition;
}
}