mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-12 13:23:29 +00:00
SEC-37: Only update HttpSession if SecurityContext has actually been changed.
This commit is contained in:
parent
494e35f009
commit
41202112bc
@ -12,7 +12,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.sf.acegisecurity.context;
|
package net.sf.acegisecurity.context;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@ -97,14 +96,9 @@ import javax.servlet.http.HttpSession;
|
|||||||
*/
|
*/
|
||||||
public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
||||||
Filter {
|
Filter {
|
||||||
//~ Static fields/initializers =============================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class);
|
protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class);
|
||||||
private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";
|
private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";
|
||||||
public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";
|
public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";
|
||||||
|
|
||||||
//~ Instance fields ========================================================
|
|
||||||
|
|
||||||
private Class context = SecurityContextImpl.class;
|
private Class context = SecurityContextImpl.class;
|
||||||
private Object contextObject;
|
private Object contextObject;
|
||||||
|
|
||||||
@ -115,8 +109,6 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
*/
|
*/
|
||||||
private boolean allowSessionCreation = true;
|
private boolean allowSessionCreation = true;
|
||||||
|
|
||||||
//~ Methods ================================================================
|
|
||||||
|
|
||||||
public void setAllowSessionCreation(boolean allowSessionCreation) {
|
public void setAllowSessionCreation(boolean allowSessionCreation) {
|
||||||
this.allowSessionCreation = allowSessionCreation;
|
this.allowSessionCreation = allowSessionCreation;
|
||||||
}
|
}
|
||||||
@ -134,8 +126,8 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
if ((this.context == null)
|
if ((this.context == null) ||
|
||||||
|| (!SecurityContext.class.isAssignableFrom(this.context))) {
|
(!SecurityContext.class.isAssignableFrom(this.context))) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"context must be defined and implement SecurityContext (typically use net.sf.acegisecurity.context.SecurityContextImpl)");
|
"context must be defined and implement SecurityContext (typically use net.sf.acegisecurity.context.SecurityContextImpl)");
|
||||||
}
|
}
|
||||||
@ -146,11 +138,13 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
/**
|
/**
|
||||||
* Does nothing. We use IoC container lifecycle services instead.
|
* Does nothing. We use IoC container lifecycle services instead.
|
||||||
*/
|
*/
|
||||||
public void destroy() {}
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response,
|
public void doFilter(ServletRequest request, ServletResponse response,
|
||||||
FilterChain chain) throws IOException, ServletException {
|
FilterChain chain) throws IOException, ServletException {
|
||||||
if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {
|
if ((request != null) &&
|
||||||
|
(request.getAttribute(FILTER_APPLIED) != null)) {
|
||||||
// ensure that filter is only applied once per request
|
// ensure that filter is only applied once per request
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
} else {
|
} else {
|
||||||
@ -163,7 +157,8 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
httpSession = ((HttpServletRequest) request).getSession(false);
|
httpSession = ((HttpServletRequest) request).getSession(false);
|
||||||
} catch (IllegalStateException ignored) {}
|
} catch (IllegalStateException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
if (httpSession != null) {
|
if (httpSession != null) {
|
||||||
httpSessionExistedAtStartOfRequest = true;
|
httpSessionExistedAtStartOfRequest = true;
|
||||||
@ -174,17 +169,17 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
if (contextFromSessionObject instanceof SecurityContext) {
|
if (contextFromSessionObject instanceof SecurityContext) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and set to SecurityContextHolder: '"
|
"Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and set to SecurityContextHolder: '" +
|
||||||
+ contextFromSessionObject + "'");
|
contextFromSessionObject + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
|
SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
|
||||||
} else {
|
} else {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '"
|
"ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" +
|
||||||
+ contextFromSessionObject
|
contextFromSessionObject +
|
||||||
+ "'; are you improperly modifying the HttpSession directly (you should always use SecurityContextHolder) or using the HttpSession attribute reserved for this class? - new SecurityContext instance associated with SecurityContextHolder");
|
"'; are you improperly modifying the HttpSession directly (you should always use SecurityContextHolder) or using the HttpSession attribute reserved for this class? - new SecurityContext instance associated with SecurityContextHolder");
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityContextHolder.setContext(generateNewContext());
|
SecurityContextHolder.setContext(generateNewContext());
|
||||||
@ -212,6 +207,9 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
httpSession = null;
|
httpSession = null;
|
||||||
|
|
||||||
// Proceed with chain
|
// Proceed with chain
|
||||||
|
int contextWhenChainProceeded = SecurityContextHolder.getContext()
|
||||||
|
.hashCode();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@ -223,9 +221,11 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
// Store context back to HttpSession
|
// Store context back to HttpSession
|
||||||
try {
|
try {
|
||||||
httpSession = ((HttpServletRequest) request).getSession(false);
|
httpSession = ((HttpServletRequest) request).getSession(false);
|
||||||
} catch (IllegalStateException ignored) {}
|
} catch (IllegalStateException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
if ((httpSession == null) && httpSessionExistedAtStartOfRequest) {
|
if ((httpSession == null) &&
|
||||||
|
httpSessionExistedAtStartOfRequest) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session");
|
"HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session");
|
||||||
@ -233,42 +233,44 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate a HttpSession only if we need to
|
// Generate a HttpSession only if we need to
|
||||||
if ((httpSession == null)
|
if ((httpSession == null) &&
|
||||||
&& !httpSessionExistedAtStartOfRequest) {
|
!httpSessionExistedAtStartOfRequest) {
|
||||||
if (!allowSessionCreation) {
|
if (!allowSessionCreation) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"The HttpSession is currently null, and the HttpSessionContextIntegrationFilter is prohibited from creating a HttpSession (because the allowSessionCreation property is false) - SecurityContext thus not stored for next request");
|
"The HttpSession is currently null, and the HttpSessionContextIntegrationFilter is prohibited from creating a HttpSession (because the allowSessionCreation property is false) - SecurityContext thus not stored for next request");
|
||||||
}
|
}
|
||||||
} else if (!contextObject.equals(
|
} else if (!contextObject.equals(
|
||||||
SecurityContextHolder.getContext())) {
|
SecurityContextHolder.getContext())) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"HttpSession being created as SecurityContextHolder contents are non-default");
|
"HttpSession being created as SecurityContextHolder contents are non-default");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
httpSession = ((HttpServletRequest) request)
|
httpSession = ((HttpServletRequest) request).getSession(true);
|
||||||
.getSession(true);
|
} catch (IllegalStateException ignored) {
|
||||||
} catch (IllegalStateException ignored) {}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"HttpSession is null, but SecurityContextHolder has not changed from default: ' "
|
"HttpSession is null, but SecurityContextHolder has not changed from default: ' " +
|
||||||
+ SecurityContextHolder.getContext()
|
SecurityContextHolder.getContext() +
|
||||||
+ "'; not creating HttpSession or storing SecurityContextHolder contents");
|
"'; not creating HttpSession or storing SecurityContextHolder contents");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If HttpSession exists, store current SecurityContextHolder contents
|
// If HttpSession exists, store current SecurityContextHolder contents
|
||||||
if (httpSession != null) {
|
// but only if SecurityContext has actually changed (see JIRA SEC-37)
|
||||||
|
if ((httpSession != null) &&
|
||||||
|
(SecurityContextHolder.getContext().hashCode() != contextWhenChainProceeded)) {
|
||||||
httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,
|
httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,
|
||||||
SecurityContextHolder.getContext());
|
SecurityContextHolder.getContext());
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("SecurityContext stored to HttpSession: '"
|
logger.debug("SecurityContext stored to HttpSession: '" +
|
||||||
+ SecurityContextHolder.getContext() + "'");
|
SecurityContextHolder.getContext() + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,5 +302,6 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean,
|
|||||||
*
|
*
|
||||||
* @throws ServletException ignored
|
* @throws ServletException ignored
|
||||||
*/
|
*/
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {}
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.sf.acegisecurity.context;
|
package net.sf.acegisecurity.context;
|
||||||
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
@ -31,12 +30,8 @@ import net.sf.acegisecurity.Authentication;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class SecurityContextImpl implements SecurityContext {
|
public class SecurityContextImpl implements SecurityContext {
|
||||||
//~ Instance fields ========================================================
|
|
||||||
|
|
||||||
private Authentication authentication;
|
private Authentication authentication;
|
||||||
|
|
||||||
//~ Methods ================================================================
|
|
||||||
|
|
||||||
public void setAuthentication(Authentication authentication) {
|
public void setAuthentication(Authentication authentication) {
|
||||||
this.authentication = authentication;
|
this.authentication = authentication;
|
||||||
}
|
}
|
||||||
@ -49,14 +44,14 @@ public class SecurityContextImpl implements SecurityContext {
|
|||||||
if (obj instanceof SecurityContextImpl) {
|
if (obj instanceof SecurityContextImpl) {
|
||||||
SecurityContextImpl test = (SecurityContextImpl) obj;
|
SecurityContextImpl test = (SecurityContextImpl) obj;
|
||||||
|
|
||||||
if ((this.getAuthentication() == null)
|
if ((this.getAuthentication() == null) &&
|
||||||
&& (test.getAuthentication() == null)) {
|
(test.getAuthentication() == null)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this.getAuthentication() != null)
|
if ((this.getAuthentication() != null) &&
|
||||||
&& (test.getAuthentication() != null)
|
(test.getAuthentication() != null) &&
|
||||||
&& this.getAuthentication().equals(test.getAuthentication())) {
|
this.getAuthentication().equals(test.getAuthentication())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,4 +71,12 @@ public class SecurityContextImpl implements SecurityContext {
|
|||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
if (this.authentication == null) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return this.authentication.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user