白话SpringSecurity认证源码分析(一)

通常来说安全框架需要做什么?

无非就是三件事情:你是谁?你能做什么?你可不可以做?

什么是认证?什么是授权?什么是鉴权?

白话来说:认证就是鉴别你是不是你,授权就是告诉你能做什么,鉴权就是你可不可以做。

 

SpringSecurity中的认证和鉴权

结合生活中的例子以及看源码的角度来认识认证和鉴权。

小明和小红周末打算去苏州乐园玩,于是从某黄牛大姐那边买了两张乐园的高级门票,里面包含了疯狂过山车、旋转大摆轮等惊险又刺激的项目,想想周末应该无比的快乐又充实。于是等啊等,周六到了。。。

 

认识Principal(令牌)

小明和小红手上的门票,其实就是令牌,用来确认是否可以进入乐园的的东西。现实生活中有很多东西都是令牌,比如身份证、学生证、残疾人证等,能够确认你不同身份。一个人身上有很多种认证你是啥身份的证件,所以令牌被设计为接口的形式,在源码中查看其常用的令牌:

image.png

重点关注:

  • OAuth2Authentication OAuth用户令牌
  • UsernamePasswordAuthenticationToken   用户名密码认证的用户令牌

怎么样得到Principal(令牌)

周六小明和小红高高兴兴的去了乐园,到了检票门口,检票大妈刷了下闸机,发现这张是假票!得重新买,不然不给进,这时候幡然悔悟啊,黄牛大姐不讲武德啊!!!于是两人去售票处买票了。到了售票处,售票员说:如果是学生,出示学生证可以打9折优惠。幸好今天小明和小红带了学生证,高高心心的买了9折的门票,顺利的进入了乐园。

结合上面的生活场景,进行了购票和验票操作,才得到了门票,其中的提供学生证购票9折优惠,就是认证操作,得到了门票就是授权行为,门票就是一张令牌。

我们常见的登录系统,填写用户名和密码,点击登录操作就是请求到后台认证,后台认证通过后返回给你一个令牌。那Spring Security中认证这操作是如何实现的呢?

认证

Spring Security 认证的实现,是通过过滤器实现的,使用过滤链,把多个过滤器串起来,根据你的令牌类型来判断是不是属于这个过滤器进行操作。

UsernamePasswordAuthenticationFilter(用户名密码授权过滤器)

核心代码解读:

image.png

以上第一步、第二步操作将我们的用户名和密码封装成用户名密码类型的令牌,第三步才开始真正的认证操作。

 

AuthenticationManager (认证管理器)

因为有很多种令牌嘛,所以不言而喻认证也有很多种方式,所以产生了认证管理器这一说法,它也是被设计为接口的形式,以下为这个接口最常见的实现类

image.png

ProviderManager 管理哪个认证提供者来认证

这个类的核心方法见下图:

image.png

第一步:得到所有实现AuthenticationProvider接口的认证类

第二步:调用认证类support方法,下图举得例子为用户名和密码的认证类

image.png

第三点:其真正认证是其实现类内部方法,按照流程,其命中的是DaoAuthenticationProvider。

DaoAuthenticationProvider 基于用户名和密码的认证

查看源码发现,这个类继承了一个父类,AbstractUserDetailsAuthenticationProvider。 认证方法部分在父类中,以下是认证方法的核心解读:

image.png

最重要的retrieveUser方法

image.png

最终走的是userDetailService方法根据用户名获取用户信息(包含密码),如何没有查找到用户,就会抛出未找到用户异常。

注意:这个userDetailService需要你注入,因为用户的资源不在框架的范畴中。

那么我们现在得到了系统里面的用户,在同输入的用户名密码进行密码的比较,就可以完成认证的操作了。接着我们回到它的父类AbstractUserDetailsAuthenticationProvider。


image.png

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

image.png

若密码相等,就接着往下执行,

image.png至此我们完成了认证的操作,返回了一个基于用户和密码的令牌。

更多相关实现项目: http://xingship.com

posted @ 2020-12-14 16:48  西瓜513  阅读(147)  评论(0)    收藏  举报