【问题标题】:Why is my Spring PreAuthFilter always called?为什么我的 Spring PreAuthFilter 总是被调用?
【发布时间】:2012-09-27 13:19:39
【问题描述】:

我的 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 上发布了相应的注销。太冗长了,这里就不介绍了。

【问题讨论】:

  • 您可以打开调试(将log4j.logger.org.springframework.security=DEBUG 添加到log4j.properties 行)并在您的问题中发布输出吗?
  • 所以问题是:注销后再次登录。?
  • 第二个问题:像/other这样的其他资源是否应该通过PRE_AUTH_FILTER运行?
  • 第一个问题:是的,因为过滤器是在/**上执行的。第二个问题:不,只有intercept-url 定义的那些。据我所知,http 匹配 / 并在其上应用整个链。

标签: spring spring-mvc configuration spring-security


【解决方案1】:

似乎您想要的是创建特殊的&lt;http&gt;,而不使用任何用于注销 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>

阅读更多关于请求匹配机制here

编辑:

@LukeTaylor 提到 如果你想创建另一个过滤器链,那么模式应该放在元素中(这是否明确记录在某处?),所以我的想法显然是没有PRE_AUTH_FILTER 的单独链不会工作。为/logout 添加了&lt;http&gt;,没有任何过滤器,这应该会阻止在注销请求时进行授权。

不过,我不知道如何防止像 /other 这样的请求应用 PRE_AUTH_FILTER。一种方法可能是放弃 &lt;http&gt; 命名空间配置到具有两个 &lt;sec:filter-chain&gt; 模式的 manual filterChainProxy 配置,但我不知道是否值得。

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

【讨论】:

  • 这很奇怪。文档说FilterChainProxy 将决定是否通过链传递请求。我想知道为什么这个请求会被通过,因为它是在 sec 强制执行但没有明确保护的。如果我更改为基本身份验证,它只会起作用,因为它需要特定的标头。这是不是设计不当?明天我会试试第二条规则。
  • 此配置看起来不正确。如果你想创建另一个过滤器链,那么模式应该放在 元素中。在这种情况下,您可能需要另一个与“/logout/*”匹配的过滤器链,放在主过滤器​​链之前。那么这些请求将不会通过身份验证过滤器进行路由。
  • 卢克,我应该改变什么来使预授权过滤器只在安全的 URL 上被调用?
  • 上面的配置不起作用。它需要一个身份验证入口点。即使我添加一个,它也会失败:原因:java.lang.IllegalArgumentException:通用匹配模式('/**')在过滤器链中的其他模式之前定义,导致它们被忽略。
  • @Xaerxess,IAE 完全正常,因为 &lt;http&gt; 都在路径 /** 上拦截。这是不允许的。我能够确定我在详细答案中写的问题的原因。
【解决方案2】:

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

这是交易:

当您在 /** 上定义 &lt;http&gt; 元素时,您要求 Spring Security 在您定义的模式下的所有路径上触发整个过滤器链。其中一个人是否需要保护并不重要。 Rob Winch 发表了一个非常helpful video。如果您仔细查看default filter stack,您将了解应用了哪些过滤器。其中有我的过滤器。

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

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

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

  1. /app/**/admin/** 等上定义一个&lt;http&gt; 元素,但这确实很麻烦,而且到处都包含重复项。我不会推荐这样的解决方案。此外,/** 中的其他 URL 上可能没有 sec 上下文。这是不希望的。
  2. 将 preauth 过滤器拆分为两个过滤器:
    1. CurrentWindowsIdentityPreAuthenticationFilter
    2. CurrentWindowsIdentityUrlAuthenticationFilter

第二个选项解决了问题。

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

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

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    • 2010-10-23
    • 1970-01-01
    • 2014-05-28
    相关资源
    最近更新 更多