弹簧&x27;s SessionFixationProtectionStrategy终止JBoss/Weld下的CDI会话
我有一个标记为@ConversationScope的对象,在向导的许多步骤之间使用 这非常有效,只是当我的用户登录时,Spring的SessionFixationProtectionStrategy调用session.invalidate()方法以使用新id重新创建一个新会话。然后,它将失效会话的属性重新附加到新会话 问题是有一个WeldListener实例绑定到sessionDestroyed事件,它将杀死绑定到HttpSession对象的@ConversationScope实例 我已经禁用了SessionFixationProtectionStrategy,现在使用的是NullAuthenticatedSessionStrategy,它什么也不做,但是我仍然希望保留会话固定策略来保护我的站点不受此影响弹簧&x27;s SessionFixationProtectionStrategy终止JBoss/Weld下的CDI会话,jboss,spring-security,cdi,jboss-weld,session-fixation,Jboss,Spring Security,Cdi,Jboss Weld,Session Fixation,我有一个标记为@ConversationScope的对象,在向导的许多步骤之间使用 这非常有效,只是当我的用户登录时,Spring的SessionFixationProtectionStrategy调用session.invalidate()方法以使用新id重新创建一个新会话。然后,它将失效会话的属性重新附加到新会话 问题是有一个WeldListener实例绑定到sessionDestroyed事件,它将杀死绑定到HttpSession对象的@ConversationScope实例 我已经禁用了
对如何解决这个问题有什么建议吗 通过在用户进行身份验证时设置自定义随机cookie,并在每次收到用户请求时进行检查,可以实现相同的效果 编写一个自定义的
AuthenticationSuccessStrategy
来设置cookie,例如:
public class MySessionAS extends SavedRequestAwareAuthenticationSuccessHandler {
/**
* Called after the user has successfully logged in.
*/
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
// Generate random value
String myAuthToken = ...
request.getSession().setAttribute("myAuthToken", myAuthToken);
Cookie myAuthCookie = new Cookie("myAppCookie", myAuthToken);
myAuthCookie.setSecure(true); // You're using HTTPS, right?
myAuthCookie.setMaxAge(-1); // It's a session cookie.
response.addCookie(cookie);
super.onAuthenticationSuccess(request, response, authentication);
}
}
并将其插入您的表单登录
配置中
然后您只需要检查值。一个很好的方法是在web中的自定义投票者
AccessDecisionManager
,或者如果这听起来太复杂,您可以使用自定义筛选器来检查用户是否经过身份验证(非空SecurityContext
),以及是否经过身份验证,确保提交的cookie的值与会话中存储的值匹配。以下是我使用的策略:
public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
boolean hadSessionAlready = request.getSession(false) != null;
if (!hadSessionAlready && !alwaysCreateSession) {
// Session fixation isn't a problem if there's no session
return;
}
// Create new session if necessary
HttpSession session = request.getSession();
if (hadSessionAlready && request.isRequestedSessionIdValid()) {
// We need to migrate to a new session
String originalSessionId = session.getId();
if (logger.isDebugEnabled()) {
logger.debug("Invalidating session with Id '" + originalSessionId +"' " + (migrateSessionAttributes ?
"and" : "without") + " migrating attributes.");
}
String id = weldAwareSessionFixationProtectionStrategyHelper.beforeInvalidateSession( request );
Map<String, Object> attributesToMigrate = extractAttributes(session);
for( String key : attributesToMigrate.keySet() ) {
session.removeAttribute( key );
}
session.invalidate();
session = request.getSession(true); // we now have a new session
if (logger.isDebugEnabled()) {
logger.debug("Started new session: " + session.getId());
}
if (originalSessionId.equals(session.getId())) {
logger.warn("Your servlet container did not change the session ID when a new session was created. You will" +
" not be adequately protected against session-fixation attacks");
}
transferAttributes(attributesToMigrate, session);
weldAwareSessionFixationProtectionStrategyHelper.afterCreateNewSession( request, id );
onSessionChange(originalSessionId, session, authentication);
}
}
您使用的是哪个spring安全版本?我使用的是spring安全3.1.0和JBoss 7
@ApplicationScoped
public class WeldAwareSessionFixationProtectionStrategyHelper {
@Inject
private HttpSessionContext httpSessionContext;
@Inject
private HttpConversationContext httpConversationContext;
public String beforeInvalidateSession( HttpServletRequest httpServletRequest ) {
String currentId = null;
if( !httpConversationContext.getCurrentConversation().isTransient() ) {
currentId = httpConversationContext.getCurrentConversation().getId();
}
httpConversationContext.deactivate();
httpConversationContext.dissociate( httpServletRequest );
httpSessionContext.deactivate();
httpSessionContext.dissociate( httpServletRequest );
return currentId;
}
public void afterCreateNewSession( HttpServletRequest httpServletRequest, String cid ) {
httpSessionContext.associate( httpServletRequest );
httpSessionContext.activate();
httpConversationContext.associate( httpServletRequest );
if( cid == null ) {
httpConversationContext.activate();
} else {
httpConversationContext.activate( cid );
}
}
}