美文网首页Spring系列(转)(完)
Spring Security Oauth2(02)

Spring Security Oauth2(02)

作者: 郭艺宾 | 来源:发表于2018-10-24 14:11 被阅读16次

    本文开始从源码的层面,讲解一些spring Security Oauth2的认证流程。本文较长,适合在空余时间段观看。且涉及了较多的源码,非关键性代码以…代替。

    获取token

    上一篇博客中我们尝试使用了password模式和client模式,有一个比较关键的endpoint:/oauth/token。从这个入口开始分析,spring security oauth2内部是如何生成token的。

    首先开启debug信息:

    可以完整的看到内部的运转流程。

    client模式稍微简单一些,使用client模式获取token

    http://localhost:8080/oauth/token? client_id=client_1&client_secret=123456&scope=select&grant_type=client_credentials

    由于debug信息太多了,我简单按照顺序列了一下关键的几个类:


    ClientCredentialsTokenEndpointFilter和DaoAuthenticationProvider

    截取关键的代码,可以分析出大概的流程。

    在请求到达/oauth/token之前经过了ClientCredentialsTokenEndpointFilter这个过滤器,关键方法如下

    用来从请求中获取clientid,clientsecret,组装成一个UsernamePasswordAuthenticationToken作为身份标识,使用容器中的顶级身份管理器AuthenticationManager去进行身份认证(AuthenticationManager的实现类一般是ProviderManager。而ProviderManager内部维护了一个List,真正的身份认证是由一系列AuthenticationProvider去完成。而AuthenticationProvider的常用实现类则是DaoAuthenticationProvider,DaoAuthenticationProvider内部又聚合了一个UserDetailsService接口,UserDetailsService才是获取用户详细信息的最终接口,而我们上一篇文章中在内存中配置用户,就是使用了UserDetailsService的一个实现类InMemoryUserDetailsManager)。UML类图可以大概理解下这些类的关系,省略了授权部分。

    图1 认证相关UML类图

    可能机智的读者会发现一个问题,我前面一片文章已经提到了client模式是不存在“用户”的概念的,那么这里的身份认证是在认证什么呢?debug可以发现UserDetailsService的实现被适配成了ClientDetailsUserDetailsService,这个设计是将client客户端的信息(clientid,clientsecret)适配成用户的信息(username,password),这样我们的认证流程就不需要修改了。

    经过ClientCredentialsTokenEndpointFilter之后,身份信息已经得到了AuthenticationManager的验证。接着便到达了TokenEndpoint。

    TokenEndpoint

    前面的两个ClientCredentialsTokenEndpointFilter和DaoAuthenticationProvider可以理解为一些前置校验,和身份封装,而这个类一看名字就知道和我们的token是密切相关的。

    省略了一些校验代码之后,真正的/oauth/token端点暴露在了我们眼前,其中方法参数中的Principal经过之前的过滤器,已经被填充了相关的信息,而方法的内部则是依赖了一个TokenGranter 来颁发token。其中OAuth2AccessToken的实现类DefaultOAuth2AccessToken就是最终在控制台得到的token序列化之前的原始类:

    一个典型的样例token响应,如下所示,就是上述类序列化后的结果:


    TokenGranter

    先从UML类图对TokenGranter接口的设计有一个宏观的认识

    图2 TokenGranter相关UML类图

    TokenGranter的设计思路是使用CompositeTokenGranter管理一个List列表,每一种grantType对应一个具体的真正授权者,在debug过程中可以发现CompositeTokenGranter 内部就是在循环调用五种TokenGranter实现类的grant方法,而granter内部则是通过grantType来区分是否是各自的授权类型。

    五种类型分别是:

    1.  ResourceOwnerPasswordTokenGranter ==> password密码模式

    2.  AuthorizationCodeTokenGranter ==> authorization_code授权码模式

    3.  ClientCredentialsTokenGranter ==> client_credentials客户端模式

    4.  ImplicitTokenGranter ==> implicit简化模式

    5.  RefreshTokenGranter ==>refresh_token 刷新token专用

    以客户端模式为例,思考如何产生token的,则需要继续研究5种授权者的抽象类:AbstractTokenGranter

    回过头去看TokenEndpoint中,正是调用了这里的三个重要的类变量的相关方法。由于篇幅限制,不能延展太多,不然没完没了,所以重点分析下AuthorizationServerTokenServices是何方神圣。

    AuthorizationServerTokenServices

    在默认的实现类DefaultTokenServices中,可以看到token是如何产生的,并且了解了框架对token进行哪些信息的关联。

    简单总结一下AuthorizationServerTokenServices的作用,他提供了创建token,刷新token,获取token的实现。在创建token时,他会调用tokenStore对产生的token和相关信息存储到对应的实现类中,可以是Redis,数据库,内存,jwt。

    总结

    本篇总结了使用客户端模式获取Token时,spring security oauth2内部的运作流程,其他模式有一定的不同,但抽象功能是固定的,只是具体的实现类会被响应地替换。阅读spring的源码,会发现它的设计中出现了非常多的抽象接口,这对我们理清楚内部工作流程产生了不小的困扰,我的方式是可以借助UML类图,先从宏观理清楚作者的设计思路,这会让我们的分析事半功倍。

    下一篇文章重点分析用户携带token访问受限资源时,spring security oauth2内部的工作流程。

    原文链接:https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247484095&idx=1&sn=a4f7a5c577b17632bee715f1d87aef39&chksm=9bd0af27aca7263124d605ceada6af8b405debf941162cf3a5a63316000dce59e4686d084df4&scene=21#wechat_redirect

    相关文章

      网友评论

        本文标题:Spring Security Oauth2(02)

        本文链接:https://www.haomeiwen.com/subject/dcbttqtx.html