我的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过滤器。当我在根网址/
上调用我的应用时,过滤器链会挂钩并运行preauth过滤器,尽管此资源不受保护。这意味着注销不能按设计工作。注销后再次执行登录。
我的实施基于org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter
类。
这是正常行为还是可以解决这个问题?我希望仅在受保护的URL上执行身份验证。
正如我所说,我不打算配置security='none'
,因为我想在所有页面上维护安全上下文。
我已在pastebin上发布了相应的注销信息。在这里包含它太冗长了。
答案 0 :(得分:1)
似乎您想要的是创建特殊的<http>
而没有任何用于注销网址的过滤器:
<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提到如果你想创建另一个过滤器链,那么模式应该放在元素中(这是明确记录的吗?),所以我的想法是单独的链而没有{{1}显然不会起作用。为PRE_AUTH_FILTER
添加了<http>
,没有任何过滤器,这可能会阻止在注销请求时进行授权。
但是,我不知道如何阻止像/logout
这样的请求应用PRE_AUTH_FILTER。一种方法可能是放弃/other
命名空间配置到manual filterChainProxy
配置有两个<http>
模式,但我不知道它是否值得。
@ Michael-O:关于异常<sec:filter-chain>
- 这很奇怪,它是你的安全XML配置吗?或许这只是Luke所说的结果(另一个IllegalArgumentException: A universal match pattern ('/**') is defined before other patterns
元素应该有模式)......
答案 1 :(得分:0)
我能够识别问题,但由于整个链的工作方式,它无法以现在的方式解决。
这是交易:
在<http>
上定义/**
元素时,要求Spring Security在您定义的模式下的所有路径上触发整个过滤器链。无论其中一个是否需要保护都无关紧要。 Rob Winch发表了非常helpful video。如果您仔细查看default filter stack,那么您将应用哪些过滤器。在这些是我的过滤器。
我的日志文件的前十行显示,由于/
与<http>
配置匹配,整个链都会被触发。最后,FilterSecurityInterceptor
看到此资源不需要保护。更重要的是,您会看到CurrentWindowsIdentityAuthenticationFilter
也被解雇并执行不需要的身份验证。
为什么呢?与基于标头的过滤器或URL处理过滤器相比,您没有触发/入口点来故意开始身份验证,无论URL是否需要保护,您都可以在不挑战客户端的情况下完成任务。定义类似<http pattern="/unprotected-url" security="none" />
之类的东西可以保存您,因为您在不受保护的路径上丢失了安全上下文。无论URL保护如何,您都希望保持客户端登录。
现在如何解决这个问题?您有两种选择:
<http>
,/app/**
上定义一个/admin/**
元素,但这真的很麻烦并且包含所有的重复。我不推荐这样的解决方案。此外,您可能不会在/**
中的其他网址上使用sec上下文。这是不希望的。CurrentWindowsIdentityPreAuthenticationFilter
CurrentWindowsIdentityUrlAuthenticationFilter
第二个选项解决了这个问题。
CurrentWindowsIdentityPreAuthenticationFilter
:保持原样并始终执行身份验证。对于脚本访问或REST请求等M2M通信非常有用。
CurrentWindowsIdentityUrlAuthenticationFilter
:非常适合人与人之间的互动。它基本上像基于表单的过滤器。如果定义了一个URL,比如说/login
,那么当您请求受保护的资源时,您将被重定向到您,并且在成功进行自动身份验证后,您将被重定向回您的实际资源。 Auth完成了。公共资源仍未经过身份验证,因为preauth过滤器仅在/login
上触发,就像基于表单一样。如果您退出,则保持退出状态。
如果春天的任何人都可以确认我的分析,我会很高兴。