匿名认证(Anonymous Authentication)

通常认为采用“默认拒绝”是一种良好的安全实践,在这种情况下,您可以明确指定允许的内容,并禁止其他内容。定义未经身份验证的用户可以访问的内容也是类似的情况,特别是对于 web 应用程序。许多站点要求用户必须对除了一些 url (例如主页和登录页面)以外的任何内容进行身份验证。在这种情况下,为这些特定 url 定义访问配置属性比为每个安全资源定义访问配置属性更容易。换句话说,有时候说 role_something 是默认需要的,并且只允许该规则的某些异常,比如用于应用程序的登录、注销和主页。您还可以从过滤器链中完全省略这些页面,从而绕过访问控制检查,但这可能由于其他原因而不可取,特别是如果页面对于经过身份验证的用户的行为不同。

这就是我们所说的匿名身份验证。注意,在“匿名身份验证”用户和未经身份验证的用户之间没有真正的概念差异。Spring Security 的匿名身份验证为您配置访问控制属性提供了更方便的方法。例如,对于 getCallerPrincipal 等 servlet API 的调用仍然返回 null,即使 SecurityContextHolder 中实际上存在匿名身份验证对象。

在其他情况下,匿名身份验证也很有用,例如审计拦截器查询 SecurityContextHolder 以确定哪个主体负责给定的操作。如果类知道 SecurityContextHolder 总是包含一个 Authentication 对象,而且从不使用 null,则可以更有效地创建类。

Configuration

当使用 HTTP 配置 Spring Security 3.0时,会自动提供匿名身份验证支持,并且可以使用 < Anonymous > 元素进行定制(或禁用)。您不需要配置这里描述的 bean,除非您使用传统的 bean 配置。

共同提供匿名身份验证特性的三个类。Token 是身份验证的一个实现,它存储应用于匿名主体的 GrantedAuthoritys。有一个相应的 AnonymousAuthenticationProvider,它被链接到 ProviderManager 中,以便 AnonymousAuthenticationToken 被接受。最后,还有一个 AnonymousAuthenticationFilter,它被链接在正常的身份验证机制之后,如果没有现有的身份验证,它会自动向 SecurityContextHolder 添加 AnonymousAuthenticationTokens 。过滤器和身份验证提供者的定义如下:

<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>

密钥在过滤器和身份验证提供者之间共享,以便前者创建的标记被后者接受[1]。userAttribute 以 usernameInTheAuthenticationToken,grantedAuthority [ ,grantedAuthority ]的形式表示。这与 InMemoryDaoImpl 的 userMap 属性的等号后面使用的语法相同。

如前所述,匿名身份验证的好处是所有 URI 模式都可以应用安全性。例如:

<bean id="filterSecurityInterceptor"
	class="org.springframework.security.web.access.intercept.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

有关匿名身份验证的讨论的最后一个例子是AuthenticationTrustResolver接口,以及它对应AuthenticationTrustResolverImpl实现。该接口提供了isAnonymous(身份验证)方法,它允许感兴趣的类考虑这种特殊类型的身份验证状态。ExceptionTranslationFilter在处理AccessDeniedExceptions时使用此接口。如果抛出AccessDeniedException异常,并且身份验证是匿名类型的,则筛选器不会抛出403(禁止)响应,而是开始AuthationEntryPoint,以便主体可以正确地进行身份验证。
这是一个必要的区别,否则主体将始终被认为是“经过身份验证的”,并且永远不会有机会通过表单、基本、摘要或一些其他正常的身份验证机制进行登录。

您经常会看到上述拦截器配置中的ROLE_ANONYMONY属性被替换为IS_AUTHENTIAD_ANAMENTIAL,这在定义访问控制时实际上是相同的。这是一个使用身份验证Voter的示例,我们将在授权一章中看到。它使用身份验证TrustResolver来处理此特定配置属性,并向匿名用户授予访问权限。AuthatedVoter方法更强大,因为它允许您区分匿名、记住我和完全经过身份验证的用户。但是,如果您不需要这个功能,那么您可以坚持使用ROLE_ANONYMON,它将由Spring Security的标准RoleVoter处理。

使用 Spring MVC 获取匿名认证

Springmvc 使用自己的参数解析器解析 Principal 类型的参数。

@GetMapping("/")
public String method(Authentication authentication) {
	if (authentication instanceof AnonymousAuthenticationToken) {
		return "anonymous";
	} else {
		return "not anonymous";
	}
}

将始终返回“not anonymous”,即使对于匿名请求也是如此。其原因是,Spring MVC使用HttpServletRequestgetMaster来解析参数,当请求是匿名的时,该参数为空。
如果你想在匿名请求中获得身份验证,可以使用@CurrentSecurityContext:

@GetMapping("/")
public String method(@CurrentSecurityContext SecurityContext context) {
	return context.getAuthentication().getName();
}

[1] 使用密钥财产不应被视为在这里提供任何真正的安全。这只是一项记账工作。如果在身份验证客户端可以构造身份验证对象(例如使用RMI调用)的场景中共享包含匿名身份验证提供者的ProviderManager,则恶意客户端可能会提交自己创建的匿名身份验证令牌(带有选定的用户名和授权列表)。如果密钥是可猜测的或可以找到的,则该令牌将被匿名提供者接受。这对于正常使用来说不是问题,但如果您使用的是RMI,那么最好使用定制的ProviderManager,它省略了匿名提供者,而不是共享您用于HTTP身份验证机制的提供者。

参考 SpringSecurity 官方文档

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值