39

我将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 节。参考文档的会话固定攻击保护说:

会话固定攻击是一种潜在风险,恶意攻击者可能通过访问站点来创建会话,然后说服另一个用户使用相同的会话登录(通过向他们发送包含会话标识符作为参数的链接,例如例子)。Spring Security 通过在用户登录时创建一个新会话来自动防止这种情况发生。如果您不需要此保护,或者它与其他一些要求冲突,您可以使用 session-fixation-protection 属性控制该行为有三个选项:

  • migrateSession - 创建一个新会话并将现有会话属性复制到新会话。这是默认设置。
  • none - 不做任何事情。原始会话将被保留。
  • newSession - 创建一个新的“干净”会话,而不复制现有会话数据。

身份验证有效,但由于我对 Spring Security 还很陌生,所以我也有一些问题需要回答:

  • 通常对于登录,我会将身份验证信息发布到j_spring_security_check并让 Spring Security 执行实际的身份验证代码。我想要保护免受会话固定攻击,当我像我一样执行程序登录时会得到它吗?如果没有,我该怎么做才能得到它?
  • 如何执行程序化注销?
  • 由于我将使用编程登录和注销,我如何禁用 Spring 拦截这些 URL?

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

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

4

6 回答 6

23

也许它不是您问题的完整答案,但也许它可能会对您有所帮助。

当您不使用编程登录时调用的代码,但可以在此处找到标准代码:

org.springframework.security.ui.webapp.AuthenticationProcessingFilter

我猜你在你的代码中受到了启发。它看起来非常相似。

同样,/j_spring_security_logout在标准方法中访问时执行的代码可在此处找到:

org.springframework.security.ui.logout.LogoutFilter

LogoutFilter 调用多个处理程序。我们正在使用的处理程序称为: org.springframework.security.ui.logout.SecurityContextLogoutHandler,因此您可能会在您的方法中调用相同的代码。

于 2009-06-19T11:04:51.037 回答
8

您确实会对会话固定攻击持开放态度。为了解决这个问题,您可以再次受到 Spring 代码的“启发”。要创建一个新会话,您显然需要访问 httpsession,因此您可能需要进行一些重构。

如果你看到方法SessionUtilsstartNewSessionIfRequired.

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

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

SecurityContextHolder.getContext().setAuthentication(null);

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

希望这可以帮助!

于 2009-06-21T20:39:41.200 回答
6

1) 程序化注销

  1. 调用 HttpServletRequest.getSession(false).invalidate
  2. 调用 SecurityContextHolder.clearContext()

2) 告诉 Spring Security 不要拦截某些 URL,这取决于你的应用程序 url 空间是如何设置的。如果您的所有页面(除了 /logIn 和 /logout)都位于上下文 /myApp 中,那么您可以这样做:

<http ....>
  <intercept-url pattern="/myApp/**" ..>
 ....
</http>
于 2009-06-23T22:26:27.117 回答
1

我遇到了程序登录问题。我调用了所有的authenticationManager.authenticate(...)SecurityContextHolder.getContext().setAuthentication(...)方法,但在会话中遇到了一些问题。我必须添加以下几行才能正确管理会话:

HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());

从上面发布的示例代码中并不清楚这一点。有关更多信息,请查看http://forum.springsource.org/showthread.php?t=69761

于 2010-11-03T13:51:40.700 回答
0

要进行编程注销,也可以抛出org.springframework.security.core.AuthenticationException. 例如,SessionAuthenticationException。在这种情况下ExceptionTranslationFilter启动注销。

于 2010-07-16T07:27:42.060 回答
0

你可以试试这个

    try {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }

        SecurityContextHolder.clearContext();

    } catch (Exception e) {
        logger.log(LogLevel.INFO, "Problem logging out.");
    }
于 2012-03-19T14:53:22.500 回答