Spring Security Authentication (认证)原理初探

本质上讲,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 对象更直观。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容