这是我正在使用的策略:
- 从当前会话中分离焊接上下文(会话和对话)。
- 复制所有会话属性后,在使其无效之前将它们从会话中删除(由于某种原因不这样做不起作用,可能是焊接中某处的会话破坏侦听器)
- 创建新会话,从上一个会话中复制属性
- 重新附加焊接上下文。
您需要复制 SessionFixationProtectionStrategy 类才能实现这一点,因为没有合适的钩子已经到位。这是 onAuthenticate。
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);
}
}
...这是 WeldAwareSessionFixationProtectionStrategyHelper
@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 );
}
}
}