我正在使用Wicket和Wicket Auth Project作为我的表示层,因此我将其与Spring Security集成在一起。这是Wicket为我进行身份验证调用的方法:
@Override
public boolean authenticate(String username, String password) {
try {
Authentication request = new UsernamePasswordAuthenticationToken(
username, password);
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
} catch (AuthenticationException e) {
return false;
}
return true;
}
我的Spring Security XML配置的内容(内部)是:
<http path-type="regex">
<form-login login-page="/signin"/>
<logout logout-url="/logout" />
</http>
<global-method-security secured-annotations="enabled" />
<authentication-manager alias="authenticationManager"/>
<authentication-provider user-service-ref="userService">
<password-encoder ref="bcryptpasswordencoder" />
</authentication-provider>
参考文档的2.3.6. Session Fixation Attack Protection部分说:
会话固定攻击是可能的潜在风险 为恶意攻击者创建一个 然后通过访问网站进行会话 说服其他用户登录 同一个会话(发送给他们一个 包含会话标识符的链接 作为参数,例如)。弹簧 安全防范这一点 通过创建新的自动 用户登录时的会话。如果您 不需要这种保护,或者它 与其他一些要求发生冲突, 你可以使用控制行为 会话固定保护 属性on,有三个 选项:
- migrateSession - 创建新会话并复制现有会话 会话属性到新会话。这是默认设置。
- none - 什么都不做。原始会话将被保留。
- newSession - 创建一个新的“干净”会话,而不复制 现有的会话数据。
身份验证有效,但我是Spring Security的新手,我也有一些问题需要解答:
j_spring_security_check
,让Spring Security执行实际的身份验证代码。我希望能够防止会话固定攻击,当我执行程序化登录时,我会得到它吗?如果没有,我还需要做些什么呢? 更新
对于会话固定攻击保护,似乎我需要使用签名startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry)
调用SessionUtils类中的方法。
如何获取我需要传递的SessionRegistry实例?我找不到任何方法为它创建别名ID,或者如何获取它的ID或名称。
答案 0 :(得分:22)
也许这不是你问题的完整答案,但可能对你有所帮助。
当您不使用程序化登录时调用的代码,但在此处可以找到标准的代码:
org.springframework.security.ui.webapp.AuthenticationProcessingFilter
我猜你在代码中受到启发。它看起来非常相似。
同样,您在标准方法中访问/j_spring_security_logout
时执行的代码也可以在此处找到:
org.springframework.security.ui.logout.LogoutFilter
LogoutFilter调用多个处理程序。我们使用的处理程序称为:
org.springframework.security.ui.logout.SecurityContextLogoutHandler
,因此您可以在方法中调用相同的代码。
答案 1 :(得分:8)
您确实会对会话录制攻击持开放态度。为了解决这个问题,你可以再次受到Spring代码的“启发”。要创建一个新会话,您显然需要访问httpsession,因此您可能需要进行一些重构。
如果您看到方法SessionUtils
。startNewSessionIfRequired
。
这会将身份验证迁移到新会话。您可能可以直接调用此方法,或者只是稍微重构代码。
对于程序化注销,只需在需要将此人注销时调用session.invalidate()
,就不会出错。从一般安全角度来看,这将完成所有必要的工作,但请记住,您可能需要清理会话中的某些内容。如果您有一组非常复杂的过滤器等,并且您需要确保用户已注销剩余的请求,那么您可以添加:
SecurityContextHolder.getContext().setAuthentication(null);
至于截取网址,您可以将它们设置为未使用的内容并忽略它!我不确定你是否可以关闭配置中的拦截 - 如果你真的想删除它,那么看看AuthenticationProcessingFilter
- 你可以自定义它。如果您这样做,那么您将不得不手动设置spring security xml而不使用提供的命名空间。这不是太难 - 看一些较旧的文档,你会看到如何做到这一点。
希望这有帮助!
答案 2 :(得分:6)
1)程序化注销
2)告诉Spring Security不要拦截某些URL,这种方式取决于你的应用程序URL空间的设置方式。如果您的所有页面(/ logIn和/ logout除外)都位于context / myApp上,那么您可以这样做:
<http ....>
<intercept-url pattern="/myApp/**" ..>
....
</http>
答案 3 :(得分:1)
我遇到程序化登录问题。我调用了所有authenticationManager.authenticate(...)
和SecurityContextHolder.getContext().setAuthentication(...)
方法但遇到了Session的一些问题。我必须添加以下行来正确管理会话:
HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
上面发布的示例代码并不清楚。有关http://forum.springsource.org/showthread.php?t=69761
的更多信息,请参阅答案 4 :(得分:0)
要进行程序化注销,还可以抛出org.springframework.security.core.AuthenticationException
。例如,SessionAuthenticationException
。在这种情况下,ExceptionTranslationFilter
会启动注销。
答案 5 :(得分:0)
你可以试试这个
try {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
SecurityContextHolder.clearContext();
} catch (Exception e) {
logger.log(LogLevel.INFO, "Problem logging out.");
}