白话SpringSecurity认证源码分析(一)
通常来说安全框架需要做什么?
无非就是三件事情:你是谁?你能做什么?你可不可以做?
什么是认证?什么是授权?什么是鉴权?
白话来说:认证就是鉴别你是不是你,授权就是告诉你能做什么,鉴权就是你可不可以做。
SpringSecurity中的认证和鉴权
结合生活中的例子以及看源码的角度来认识认证和鉴权。
小明和小红周末打算去苏州乐园玩,于是从某黄牛大姐那边买了两张乐园的高级门票,里面包含了疯狂过山车、旋转大摆轮等惊险又刺激的项目,想想周末应该无比的快乐又充实。于是等啊等,周六到了。。。
认识Principal(令牌)
小明和小红手上的门票,其实就是令牌,用来确认是否可以进入乐园的的东西。现实生活中有很多东西都是令牌,比如身份证、学生证、残疾人证等,能够确认你不同身份。一个人身上有很多种认证你是啥身份的证件,所以令牌被设计为接口的形式,在源码中查看其常用的令牌:

重点关注:
- OAuth2Authentication OAuth用户令牌
- UsernamePasswordAuthenticationToken 用户名密码认证的用户令牌
怎么样得到Principal(令牌)
周六小明和小红高高兴兴的去了乐园,到了检票门口,检票大妈刷了下闸机,发现这张是假票!得重新买,不然不给进,这时候幡然悔悟啊,黄牛大姐不讲武德啊!!!于是两人去售票处买票了。到了售票处,售票员说:如果是学生,出示学生证可以打9折优惠。幸好今天小明和小红带了学生证,高高心心的买了9折的门票,顺利的进入了乐园。
结合上面的生活场景,进行了购票和验票操作,才得到了门票,其中的提供学生证购票9折优惠,就是认证操作,得到了门票就是授权行为,门票就是一张令牌。
我们常见的登录系统,填写用户名和密码,点击登录操作就是请求到后台认证,后台认证通过后返回给你一个令牌。那Spring Security中认证这操作是如何实现的呢?
认证
Spring Security 认证的实现,是通过过滤器实现的,使用过滤链,把多个过滤器串起来,根据你的令牌类型来判断是不是属于这个过滤器进行操作。
UsernamePasswordAuthenticationFilter(用户名密码授权过滤器)
核心代码解读:

以上第一步、第二步操作将我们的用户名和密码封装成用户名密码类型的令牌,第三步才开始真正的认证操作。
AuthenticationManager (认证管理器)
因为有很多种令牌嘛,所以不言而喻认证也有很多种方式,所以产生了认证管理器这一说法,它也是被设计为接口的形式,以下为这个接口最常见的实现类

ProviderManager 管理哪个认证提供者来认证
这个类的核心方法见下图:

第一步:得到所有实现AuthenticationProvider接口的认证类
第二步:调用认证类support方法,下图举得例子为用户名和密码的认证类

第三点:其真正认证是其实现类内部方法,按照流程,其命中的是DaoAuthenticationProvider。
DaoAuthenticationProvider 基于用户名和密码的认证
查看源码发现,这个类继承了一个父类,AbstractUserDetailsAuthenticationProvider。 认证方法部分在父类中,以下是认证方法的核心解读:

最重要的retrieveUser方法

最终走的是userDetailService方法根据用户名获取用户信息(包含密码),如何没有查找到用户,就会抛出未找到用户异常。
注意:这个userDetailService需要你注入,因为用户的资源不在框架的范畴中。
那么我们现在得到了系统里面的用户,在同输入的用户名密码进行密码的比较,就可以完成认证的操作了。接着我们回到它的父类AbstractUserDetailsAuthenticationProvider。

这个additionalAuthenticationChecks就是进行密码的比较操作,里面的执行操作见下图。

若密码相等,就接着往下执行,
至此我们完成了认证的操作,返回了一个基于用户和密码的令牌。
更多相关实现项目: http://xingship.com

浙公网安备 33010602011771号