我在用 便门 与我的表示层的 Wicket Auth 项目一起,因此我将其与 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。会话固定攻击防护 参考文档中说:

在可能的情况下,会话固定攻击是一种潜在风险 让恶意攻击者创建一个 会话,然后 说服其他用户登录 相同的会话(通过向他们发送 包含会话标识符的链接 例如,作为参数)。春天 安全性可防止这种情况发生 通过创建新的 会话。如果你 不需要此保护,或者它 与其他一些要求冲突, 您可以使用以下命令来控制行为 会话固定保护 属性 ,它有三个 选项:

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

身份验证有效,但由于我对 Spring Security 相当陌生,我有一些问题也需要答案:

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

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

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

有帮助吗?

解决方案

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

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

org.springframework.security.ui.webapp.AuthenticationProcessingFilter

我猜你的代码中受到了这一点的启发。看起来很相似。

类似地,当您访问时执行的代码 /j_spring_security_logout 在标准方法中,可以在这里找到:

org.springframework.security.ui.logout.LogoutFilter

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

其他提示

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

如果你看到这个方法 SessionUtils.startNewSessionIfRequired.

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

至于编程注销,您只需调用就不会犯太大的错误 session.invalidate() 当您需要将该人注销时。从一般安全角度来看,这将执行所有必要的操作,但请记住,尽管您可能需要清理会话中的一些内容。如果您有一组非常复杂的过滤器等。并且您需要确保用户在请求的其余部分中已注销,然后您可以添加:

SecurityContextHolder.getContext().setAuthentication(null);

至于拦截 url,你可以将它们设置为未使用的内容并忽略它!我不确定你是否可以在配置中关闭拦截 - 如果你真的想删除它,那么看看 AuthenticationProcessingFilter - 你可以定制这个。如果您这样做,那么您将必须手动设置 spring security xml 并且不使用提供的名称空间。不过这并不太难——看看一些旧的文档,你就会知道如何做到这一点。

希望这可以帮助!

1) 程序化注销

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

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

<http ....>
  <intercept-url pattern="/myApp/**" ..>
 ....
</http>

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

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

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

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

你可以试试这个

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

        SecurityContextHolder.clearContext();

    } catch (Exception e) {
        logger.log(LogLevel.INFO, "Problem logging out.");
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top