程序化使用Spring Security

时间:2009-06-18 14:40:14

标签: java spring spring-security wicket

我正在使用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执行实际的身份验证代码。我希望能够防止会话固定攻击,当我执行程序化登录时,我会得到它吗?如果没有,我还需要做些什么呢?
  • 如何执行程序化注销?
  • 由于我将使用程序化登录和注销,如何禁止Spring拦截这些URL?

更新 对于会话固定攻击保护,似乎我需要使用签名startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry)调用SessionUtils类中的方法。

如何获取我需要传递的SessionRegistry实例?我找不到任何方法为它创建别名ID,或者如何获取它的ID或名称。

6 个答案:

答案 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,因此您可能需要进行一些重构。

如果您看到方法SessionUtilsstartNewSessionIfRequired

这会将身份验证迁移到新会话。您可能可以直接调用此方法,或者只是稍微重构代码。

对于程序化注销,只需在需要将此人注销时调用session.invalidate(),就不会出错。从一般安全角度来看,这将完成所有必要的工作,但请记住,您可能需要清理会话中的某些内容。如果您有一组非常复杂的过滤器等,并且您需要确保用户已注销剩余的请求,那么您可以添加:

SecurityContextHolder.getContext().setAuthentication(null);

至于截取网址,您可以将它们设置为未使用的内容并忽略它!我不确定你是否可以关闭配置中的拦截 - 如果你真的想删除它,那么看看AuthenticationProcessingFilter - 你可以自定义它。如果您这样做,那么您将不得不手动设置spring security xml而不使用提供的命名空间。这不是太难 - 看一些较旧的文档,你会看到如何做到这一点。

希望这有帮助!

答案 2 :(得分:6)

1)程序化注销

  1. 调用HttpServletRequest.getSession(false).invalidate
  2. 调用SecurityContextHolder.clearContext()
  3. 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.");
    }