これが私が使用している戦略です:
- 現在のセッションから溶接コンテキスト (セッションと会話) を切り離します。
- すべてのセッション属性をコピーした後、セッションを無効にする前にそれらをセッションから削除します (何らかの理由でこれを行わないと機能しません。おそらく、溶接のどこかにあるセッション破壊リスナーです)。
- 新しいセッションを作成し、前のセッションから属性をコピーします
- 溶接コンテキストを再接続します。
適切なフックが既に配置されていないため、これを実装できるように 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 );
}
}
}