通常考虑的一个好的安全事件是采取“deny-by-default”(默认拒绝所有请求的方式)
这种情况下,你可以明确指定允许哪些,然后拒绝其他所有操作。
定义未认证用户可以做些什么,也是一种简单情况,特别是对于web应用。
多数网站要求用户必须通过一些途径进行认证,不仅仅是一些URL(比如,首页和登陆页面)。
在这种情况下,更简单的定义访问配置属性,为这些特殊的URL,而不是把每个资源都当做被保护的资源。
不同的是,有时它最好被成为ROLE_SOMETHING
,默认是这样要求的,
对于这种规定,只有几个例外,比如,登陆,注销,应用的首页。
你也可以从过滤器链中完全忽略他们,这样就可以通过安全控制的检测,
但是,对于其他原因这些不好的,特别是,这些页面的行为与已认证用户不同。
这就是为什么我们使用匿名认证的原因,注意这里没有一个真正的理论来区分
“匿名认证”的用户和未认证用户。spring security匿名认证只是给你一个
更方便的方式来配置你的权限控制属性,调用servlet API,比如getCallerPrincipal
比如,也会返回null,即使这里已经有一个匿名认证对象在SecurityContextHolder
里的。
这里有一些其他匿名认证发挥作用的请抗,比如当一个审计拦截器查询
SecurityContextHolder
来验证哪些主体用来处理给定的操作。
类可以更好的工作,如果它们知道SecurityContextHolder
里总是包含一个Authentication
对象,
永远不会是null。
当使用spring security 3.0的HTTP配置时,就自动提供了对匿名认证的支持。
可以使用<anonymous>
元素进行自定义(或禁用)。
你不需要在这里配置bean,除非使用了以前的bean配置方式。
Spring Security提供三个类来一起提供匿名认证功能。
AnonymousAuthenticationToken
实现了Authentication
,保存着GrantedAuthority
[],用来处理匿名主体。
有一个对应的需要链入ProviderManager
的AnonymousAuthenticationProvider
,可以从中获得AnonymousAuthenticationTokens
。
最后是AnonymousAuthenticationFilter
,需要串链到普通认证机制后面,如果还没有存在的Authentication
的话,它会自动向SecurityContextHolder
添加一个AnonymousAuthenticationToken
。
过滤器和认证提供器的配置如下:
<bean id="anonymousAuthFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter"> <property name="key" value="foobar"/> <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/> </bean> <bean id="anonymousAuthenticationProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider"> <property name="key" value="foobar"/> </bean>
这个 key
会在过滤器和认证提供器之间共享,
这样创建的标记可以在以后用到。[12]
userAttribute
表达式的格式是usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]
。
这和InMemoryDaoImpl
中userMap
属性的语法一样。
如上面所讲的,匿名认证的好处是,可以对所有的URL模式都进行安全配置。 比如:
<bean id="filterSecurityInterceptor" class="org.springframework.security.intercept.web.access.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/> <property name="securityMetadata"> <security:filter-security-metadata-source> <security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/**' access='ROLE_USER'/> </security:filter-security-metadata-source> </property> </bean>
简略对匿名认证的讨论,就是AuthenticationTrustResolver
接口,它对应着AuthenticationTrustResolverImpl
实现。
这个接口提供了一个isAnonymous(Authentication)
方法,允许感兴趣的类评估认证的特殊状态类型。
在处理AccessDeniedException
异常的时候,ExceptionTranslationFilter
使用这个接口。
如果抛出了一个AccessDeniedException
异常,而且认证是匿名类型,那么不会抛出403(禁止)响应,这个过滤器会展开AuthenticationEntryPoint
,这样主体可以正确验证。
这是一个必要的区别,否则主体会一直被认为“需要“认证””,没有机会通过表单,摘要,或其他普通的认证机制登录。
你会经常看到ROLE_ANONYMOUS
属性,在上面的拦截器配置中,
被替换成IS_AUTHENTICATED_ANONYMOUSLY
,
这在定义权限控制时是完全相同的。
这时一个使用AuthenticatedVoter
的例子,可以参考验证章节。
它使用一个AuthenticationTrustResolver
来处理这个特殊的配置属性,并给匿名用户授权。
AuthenticatedVoter
的方式更强大,因为它允许你区别
匿名,rememberMe和完全认证用户。如果你不需要这些功能,你可以直接使用
ROLE_ANONYMOUS
,这会被Spring Security的标准
RoleVoter
处理。
[12] key
参数应该没有提供任何真实的安全。
它仅仅用来做一个标志。如果你共享了一个ProviderManager
包含了一个AnonymousAuthenticationProvider
,在一个场景中。
可能对于一个认证客户端,创建Authentication
对象
(比如通过RMI调用),然后一个恶意的可能提交一个
AnonymousAuthenticationToken
,它会创建自己
(选择用户名和权限队列)。如果key
可以被猜出来,或可以被找到,
这个token就可能被匿名提供者获得。这不是一个通常使用中的问题,但是如果你使用RMI,
你最好使用一个自定义的ProviderManager
,这可以避免匿名供应器
共享你使用的HTTP验证机制。