1.认证模块

CAS认证处理器主要由一个认证管理器控制,该管理器负责协调认证处理器的工作。

要了解该模块,必须知道下面几个核心名词(组件):

  • credentials

    凭证,证明用户身份的object,比如我们用用户名密码登录的时候,对应一个UsernamePasswordCredential
    使用CAS的委托登录时,对应ClientCredential

  • principal

    主体,及经过认证后,用来保存用户信息的object,见:org.apereo.cas.authentication.principal.Principal

  • AuthenticationManager

    认证管理器,认证的核心

  • AuthenticationHandler

    认证处理器,主要功能就是上面提到的凭证认证,还有属性解析

  • PrincipalResolver

    主体解析器,用于获取principal。

    有的人会有疑问,上面认证结果已经返回了一个principal,为啥这里又出现一个解析器呢,
    上面的认证处理只是得到一个简单的 principal,我们可能希望从其他地方获取我们想要的属性,比如从别的数据库或服务拿数据,
    具体我们下面说

1.1 认证管理器

认证管理器维护了一堆认证处理器,这些处理器是真正实现了认证的核心,
比如使用用户名、密码登录,会有一个处理器来做数据库操作,然后返回一个principal。

它主要包括 凭证认证主体解析认证协议检查 三步操作。

  • 凭证认证 – 验证凭证,返回一个 principal,你可以配置了多种认证方式,每个认证都会返回一个 principal

  • 主体解析 – 见 PrincipalResolver

  • 认证协议检查 – 一般不用配置该项,如果你配置了协议检查,管理器会检查你上面的所有认证结果:

    • all – 这里并不是说,你配置了多少认证方式,就必须全部认证通过,而是,你有几个credentials,就需要认证成功几次,
      即credentials.size == successes.size,比如配置多个认证方式(比如:账号、邮箱、手机号登录),通过邮箱认证成功,
      就满足了当前认证;
    • any – 有任意一个认证成功;该协议有个tryAll参数,目前没搞懂什么作用,暂时设置为false
    • uniquePrincipal – 只允许一个principalId存在,意思就是如果当前账号已经在某个地方登陆过了,就不允许再次登陆,
      他的做法是,遍历所有的TGT,检查其中的principal.id,是否与当前的principal.id系统。
    • *notPrevented – 认证过程不出现PreventedException,且满足any认证协议
    • *req(required)- 指定的认证处理器如果认证成功,则满足检查
    • *groovy – 执行groovy脚本,允许指定多个,see Configuration-Properties.html#groovy-1
    • *rest – 通过调用接口进行检查,see Configuration-Properties.html#rest-1

    认证协议相关配置:authentication-policy

    根据源码[org/apereo/cas/config/CasCoreAuthenticationPolicyConfiguration#authenticationPolicyExecutionPlanConfigurer],
    认证协议只能配置一种(所以文档中说的遍历policy纯属胡扯),如果你配置了多种,也是按代码中的优先级,进行配置,优先级:

    req > all > notPrevented > uniquePrincipal > groovy > rest > any

1.2 认证处理器

上面提到了认证的核心是认证处理器,那么什么是认证处理器?
顾名思义,就是认证的地方,用来处理凭证、解析principal(也可以认为获取用户属性),它的入口需要一个credentials,
最常见的就是 UsernamePasswordCredential,即用户名密码登录的入参,
出口是一个 principal,它包含 用户名 和 需要返回的属性(principal_attribute_list)

这个给一个 credentials 与认证处理器的对照表:

credentials authn handler 场景
UsernamePasswordCredential AbstractJdbcUsernamePasswordAuthenticationHandler 账号密码认证
ClientCredential ClientAuthenticationHandler 三方认证,如github认证

1.3 主体(principal)解析器

principal解析器是用来解析用户信息主体的,

每一个 PrincipalResolver 都会解析出一个principal,最后合并attributes,
常用的PrincipalResolver有:

  • ChainingPrincipalResolver

    链式解析,遍历每一个解析器,得到principal列表,最后合并principals:

    • principalId – 存在多个 principal 的话,id 取最后一个 principal 的id
    • attributes – 合并map,也会涉及到属性重命名

    一般只会包含 EchoingPrincipalResolver, PersonDirectoryPrincipalResolver 两个

  • EchoingPrincipalResolver

    如果参数Principal不为空,直接返回,得到的这个principal,也可以看做认证时,就已经拿到的principal

    比如你使用用户名密码登录的方式,会配置获取密码的SQL,比如:

    select username,password from user where user=?

    认证成功后,username, password就会被当做属性,进行collect,然后set到principal

  • PersonDirectoryPrincipalResolver

    根据cas.authn.attributeRepository配置,从数据库中获取属性

  • ProxyingPrincipalResolver

    代理解析器,不常用,我们可以通过设置principalFactory来自定义解析方法

配置:CasCoreAuthenticationPrincipalConfiguration#personDirectoryPrincipalResolver

2. 总结

结合源码来总结一下认证的流程就是,对于任何给出的凭证,认证管理器都将会做如下操作:

  • 遍历所有的认证处理器,进行下面所有步骤:
    • 如果处理器支持该凭证(credentials),则尝试认证
    • 如果认证成功,尝试解析principal
    • 检查认证处理器是否配置了principal解析器
    • 如果处理器配置了解析器,尝试用解析器认证credentials
    • 如果没有配置解析器,直接返回认证处理器解析的principal
    • 检查是否满足安全协议
    • 如果满足安全协议,则立即返回
    • 如果不满足安全协议,则继续执行
    • 如果所有的凭证都不满足安全协议,抛出 AuthenticationException

最后来个流程图,更清晰的了解这个过程(plantuml画流程图好low):

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注