2

我的 Spring 3.1 应用程序配置如下

<http use-expressions="true" entry-point-ref="http401UnauthorizedEntryPoint">

    <intercept-url pattern="/app/demo" access="hasRole('Demo')" />
    <intercept-url pattern="/app/**" access="isAuthenticated()" />
    <intercept-url pattern="/admin/**" access="hasRole('Admin')" />

    <custom-filter position="PRE_AUTH_FILTER"
        ref="currentWindowsIdentityAuthenticationFilter" />

    <logout invalidate-session="true" delete-cookies="JSESSIONID"
        logout-url="/logout" logout-success-url="/logout-success" />

</http>

我写了一个自定义的 preauth 过滤器。当我在根 URL 调用我的应用程序时,/过滤器链会挂接并运行 preauth 过滤器,尽管此资源不受保护。这意味着注销无法按设计工作。注销后再次执行登录。

我的实现是基于org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter类的。

这是正常行为还是可以通过某种方式解决?我希望仅在受保护的 URL 上执行身份验证。

正如我的旁注,我不打算配置security='none',因为我想维护所有页面上的安全上下文。

我已经在pastebin上发布了适当的注销。过于冗长,无法包含在此处。

4

2 回答 2

1

似乎您想要的是在<http>没有任何注销 URL 过滤器的情况下创建特殊的:

<http pattern="/logout/**" security="none" />

<http use-expressions="true" entry-point-ref="http401UnauthorizedEntryPoint">

    <intercept-url pattern="/app/demo" access="hasRole('Demo')" />
    <intercept-url pattern="/app/**" access="isAuthenticated()" />
    <intercept-url pattern="/admin/**" access="hasRole('Admin')" />

    <custom-filter position="PRE_AUTH_FILTER"
        ref="currentWindowsIdentityAuthenticationFilter" />

    <logout invalidate-session="true" delete-cookies="JSESSIONID"
        logout-url="/logout" logout-success-url="/logout-success" />

</http>

在此处阅读有关请求匹配机制的更多信息。

编辑:

@LukeTaylor 提到,如果您想创建另一个过滤器链,那么该模式应该进入元素中(这是否明确记录在某处?),所以我使用单独链的想法PRE_AUTH_FILTER显然行不通。<http>/logout没有任何过滤器的情况下添加,这应该会阻止在注销请求时进行授权。

不过,我不知道如何防止像/other应用 PRE_AUTH_FILTER 这样的请求。一种方法可能是放弃<http>命名空间配置以使用两种模式手动filterChainProxy<sec:filter-chain>配置,但我不知道这是否值得。

@Michael-O:关于异常IllegalArgumentException: A universal match pattern ('/**') is defined before other patterns- 很奇怪,它是您的整个 XML 安全配置吗?或者也许这只是卢克所说的结果(另一个<http>元素应该有模式)......

于 2012-09-27T15:37:09.993 回答
0

我能够确定问题,但由于整个链条的工作方式,它无法以现在的方式解决。

这是交易:

当您定义一个<http>元素时,/**您要求 Spring Security 在您定义的模式下的所有路径上触发整个过滤器链。其中一个人是否需要保护并不重要。Rob Winch 发布了一个非常有用的视频。如果您仔细查看默认过滤器堆栈,您将应用哪些过滤器。其中有我的过滤器。

我的日志文件的前十行显示整个链都被触发,因为/<http>配置匹配。最后,FilterSecurityInterceptor发现该资源不需要保护。此外,您会看到 也CurrentWindowsIdentityAuthenticationFilter被触发并执行了不需要的身份验证。

为什么?与基于标头的过滤器或 URL 处理过滤器相比,您没有触发/入口点来故意开始身份验证,无论 URL 是否需要保护,您都无需挑战客户端即可。定义这样<http pattern="/unprotected-url" security="none" />的内容绝对不会为您节省任何费用,因为您会丢失未受保护路径上的安全上下文。无论 URL 保护如何,您都希望让您的客户保持登录状态。

现在如何解决这个问题?你有两个选择:

  1. 在 上定义一个<http>元素/app/**/admin/**依此类推,但这确实很麻烦,并且到处都包含重复。我不会推荐这样的解决方案。此外,您可能不会在/**. 这是不希望的。
  2. 将 preauth 过滤器拆分为两个过滤器:
    1. CurrentWindowsIdentityPreAuthenticationFilter
    2. CurrentWindowsIdentityUrlAuthenticationFilter

第二个选项解决了这个问题。

CurrentWindowsIdentityPreAuthenticationFilter:保持原样并始终执行身份验证。对于脚本访问或 REST 请求等 M2M 通信非常有帮助。 CurrentWindowsIdentityUrlAuthenticationFilter: 非常适合人际交往。它的工作原理基本上类似于基于表单的过滤器。如果定义一个 URL,比如说/login,当您请求受保护的资源时,您将被重定向到,并且在成功自动验证后,您将被重定向回您的实际资源。认证完成。公共资源保持未经身份验证,因为 preauth 过滤器/login仅像基于表单一样被触发。如果您退出,您将保持退出状态。

如果 Spring 的任何人能证实我的分析,我会很高兴。

于 2012-09-29T22:09:22.123 回答