Spring Security

Spring Security Authentication (

2018-04-25  本文已影响181人  又语

本质上讲,Spring Security 是通过过滤器(Filter)和拦截器(Interceptor)实现应用安全控制。Spring Security 中定义和使用了很多的过滤器和拦截器,针对认证过程重点讲解:AbstractAuthenticationProcessingFilter

Spring Security 有一个被称作“authentication mechanism”的功能用来收集用户代理(通常是浏览器)提交的用于认证的详细身份信息(通常是用户名和密码),参看 Spring Security Reference 9.4.3 Authentication Mechanism

AbstractAuthenticationProcessingFilter 用于拦截认证请求,参看 Spring Security API 文档 中对 AbstractAuthenticationProcessingFilter 类的描述就可以发现,它是基于浏览器和 HTTP 认证请求的处理器,可以理解为它就是 Spring Security 认证流程的入口。

整个认证流程如下:
AbstractAuthenticationProcessingFilter 收集用于认证的用户身份信息(通常是用户名和密码),并基于这些信息构造一个 Authentication 请求对象,AbstractAuthenticationProcessingFilter 只是一个虚类,查看 Spring Security API 文档 可以看到 Spring Security 提供了几个实现类:
CasAuthenticationFilter
OAuth2LoginAuthenticationFilter
OpenIDAuthenticationFilter
UsernamePasswordAuthenticationFilter
最常使用的应该是 UsernamePasswordAuthenticationFilter,其它类都应用于特定的场景。
AbstractAuthenticationProcessingFilter 类将构造的 Authentication 请求对象呈现给 AuthenticationManagerAbstractAuthenticationProcessingFilter 类有以下方法设置和获取 AuthenticationManager

protected AuthenticationManager getAuthenticationManager()

public void setAuthenticationManager(AuthenticationManager authenticationManager)

AuthenticationManager 只是一个接口,Spring Security 提供了一个默认实现 ProviderManagerProviderManager 在接收到 AbstractAuthenticationProcessingFilter 传递过来的 Authentication 请求对象后并不会执行认证处理,它持有一个 AuthenticationProvider 的列表,ProviderManager 委托列表中的 AuthenticationProvider 处理认证请求;
AuthenticationProvider 也只是接口,Spring Security 提供了很多此接口的实现,如 DaoAuthenticationProviderLdapAuthenticationProviderJaasAuthenticationProvider 等,现在暂时不关心这些具体实现。列表中的 AuthenticationProvider 会依次对 Authentication 请求对象进行认证处理,如果认证通过则返回一个完全填充的 Authentication 对象(后面会解释什么是“完全填充”),如果认证不通过则抛出一个异常(注意对抛出的异常有类型要求)或直接返回 null。如果列表中的所有 AuthenticationProvider 都返回 null,则 ProviderManager 会抛出 ProviderNotFoundException 异常;
⑤ 认证通过后 AuthenticationProvider 返回完全填充的 Authentication 对象给 ProviderManagerProviderManager 继续向上返回给 AbstractAuthenticationProcessingFilterAbstractAuthenticationProcessingFilter 会继续返回。
⑥ Spring Security 的“authentication mechanism”在接收到一个完全填充的 Authentication 对象返回后会认定认证请求有效,并将此 Authentication 对象放入 SecurityContextHolder。关于 Spring Security “authentication mechanism”的介绍可以参看 Spring Security Reference 9.4.3 Authentication Mechanism
SecurityContextHolder 是 Spring Security 最基础的对象,用于存储应用程序当前安全上下文的详细信息,这些信息后续会被用于授权。有关 SecurityContextHolder 的更多信息请参看 Spring Security Reference 9.2.1 SecurityContextHolder, SecurityContext and Authentication Objects

至此,Spring Security 的认证流程已介绍完毕,但还缺少对两个十分常见的接口的说明:UserDetailsUserDetailsService

Spring Security API 文档UserDetails 的说明如下:
Implementations are not used directly by Spring Security for security purposes. They simply store user information which is later encapsulated into Authentication objects. This allows non-security related user information (such as email addresses, telephone numbers etc) to be stored in a convenient location.
从中可以看出 UserDetails 只是用于存储用户信息并最终封装到 Authentication 对象中。

Spring Security API 文档UserDetailsService 的说明如下:
Core interface which loads user-specific data.
It is used throughout the framework as a user DAO and is the strategy used by the DaoAuthenticationProvider.
The interface requires only one read-only method, which simplifies support for new data-access strategies.
从中可以看出 UserDetailsService 只定义了一个只读方法,返回一个 UserDetails 接口对象。

UserDetails loadUserByUsername(java.lang.String username)

实际上,UserDetailsServiceUserDetails 只是构造 Authentication 对象的一个过程。UserDetailsService 可以作为 AuthenticationProvider 的一个属性,在 AuthenticationProvider 执行请求认证时调用 UserDetailsServiceloadUserByUsername 方法返回一个 UserDetails 对象,并使用此 UserDetails 对象封装最终的 Authentication 对象,事实上这也就是 Spring Security 预置的一些AuthenticationProvider 实现类使用的方法,如 DaoAuthenticationProvider,可以查看 Spring Security API 文档 进一步了解 DaoAuthenticationProvider 实现细节。

在大多数情况下,如果需要定制认证过程,建议直接实现 AuthenticationProvider,这样做更有意义,在 AuthenticationProviderauthenticate 方法中直接封装 Authentication 对象,这比引用一个 UserDetailsService 实现返回一个 UserDetails 对象后再封装成最终的 Authentication 对象更直观。

上一篇下一篇

猜你喜欢

热点阅读