一、关于oauth.2协议
客户端去访问服务端资源,要经过以下步骤:
1、客户端请求认证服务器,获取到一个授权码(认证服务器上提前注册了客户端
的ip、端口、秘钥等信息)。
2、返回授权码到客户端,这个授权码是一次性的,
并且和认证信息authentication是一一对应的。
3、客户端带上授权码访问认证服务器,
通过授权码可以找到对应的authentication(认证信息),
生成token将token存入redis
(token值为key,value为通过认证信息查出来的鉴权信息),
再将token返回给客户端。
4、客户端携带token去访问资源服务器,资源服务器和认证服务器连接了
同一个redis,所以可以查到对应的token,从而通过认证。
5、通过认证后,进入鉴权阶段。token值为key,value就是可以访问的url列表。
二、授权模式
1、授权码模式
就是我上面说的那种模式,也是用得最多的,适用于合作商之间的系统授权。
生成的授权码是一次性的,必须通过授权码才可以访问到获取token的端口。
2、密码模式
适用于本公司内部的产品授权,
第三方应用之间用我方提供的认证账号和密码请求token。
也就是客户端直接携带账号密码请求认证服务器,获取token。
三、oauth2.0认证服务器配置
1、ClientDetailsServiceConfigurer:
在认证服务器注册客户端的信息,
client_id、client_secret,认证模式,
访问的权限(获取token后可以访问哪些资源),token的有效期,
刷新token的有效期。
2、AuthorizationServerEndpointsConfigurer:
设置token是如何产生的,存在哪里,
当客户端访问获取token的端点的时候,
就会根据这里的配置来获取token。
3、AuthorizationServerSecurityConfigurer:
用来配置令牌端点(Token Endpoint)的安全约束.
不让oauth2.0提供的访问和刷新令牌的url被拦截。
下面是框架提供的URL路径:
/oauth/authorize 获取授权端点
/oauth/token 获取令牌端点
/oauth/confirm_access 用户批准授权的端点
/oauth/error 用于渲染授权服务器的错误
/oauth/check_token 资源服务器解码access token,用于验证token
有两个资源是需要UI,它们分别是/oauth/confirm_access和/oauth/error。
提交授权码和授权失败页面。如果不想用框架默认的,可以用
@RequestMappings注解来映射这些端点,相当于重写这些端点,进行自定义。
四、oauth2.0客户端配置
配置文件里面表示这是个oauth客户端
指定在这个体系中的client-id和client-secret
指定当前客户端从认证服务器的获取token和获取认证码的地址。
启动类加上注解@EnableOAuth2Sso
用redis存储token的方案如下:
实际上就是将token存入到认证服务器的redis里面,
资源服务器要连接认证服务器的redis。
这种方式的缺点是资源服务器要依赖认证服务器的redis。
五、授权码模式流程
1、我在页面上点击微信登录,弹出微信认证页面。
2、在微信认证页面上输入账号密码,在认证服务器上完成认证。
3、完成认证后,认证服务器会返回一个授权码(这个授权码是一次性的,并且和认证信息authentication是一一对应的),然后返回授权码到刚才的授权地址,也就是返回到客户端。
4、点击同意授权,客户端会携带授权码,去认证服务器里面找到对应的authentication,生成token,存入redis,key是token字符串,value是authentication。然后返回token到客户端服务器。
5、客户端服务器携带token,就可以在资源服务器里面拿到对应的信息,资源服务器也是连接了redis的,通过token可以找到userDatils。返回要请求的信息。
6、请求到资源服务器中的信息后,再跟进这种信息做客户端的一些业务操作(比如客户端的注册和登录操作)
总体来说就是
分两种情况:
<1>、客户端请求的资源是分用户权限的
客户端需要先重定向到认证服务器的某个方法url,输入账户密码,
在认证服务器里面完成认证,并且与某个一次性的授权码进行绑定,
然后返回这个授权码给客户端(通过认证服务器的回调url)。
客户端携带这个授权码访问认证服务器,找到对应的authentication,
通过算法生成token。
将key为token,value为authentication的数据存到redis里面。
然后将token返回到客户端(和刚才的授权码返回地址一样)。
客户端携带这个token访问资源服务器,就可以通过redis找到对应的
authentication信息。发现是通过认证的,就可以进行鉴权验证,
从而访问到需要的资源,然后进行返回。
<2>、客户端请求的资源是不分用户权限的
客户端直接访问资源路径,这个时候会被拦截到认证服务器,
认证服务器返回认证授权码(通过认证服务器设置的客户端id或秘钥,
就可以判断是否有资格生成授权码)。
客户端携带授权码,请求认证服务器,可以生成token,同样存入redis。
然后返回到客户端。至于当前token能够访问那些权限,
是通过认证服务器的配置scope控制的。
客户端携带token访问资源服务器,资源服务器和认证服务器连接同一个redis,
就可以获取到具体的权限,进行资源访问并返回。
7、授权码模式加jwt:
和上面的流程差不多,区别就在于,可以通过authentication生成一个jwt字符串,
返回给客户端。
客户端携带jwt字符串到资源服务器,可以通过解密的方式,完成认证鉴权。
不需要存入reids,认证服务器和资源服务器就不需要连接同一个redis了,
所有的认证信息都保存在客户端,于服务器无关。
8、密码模式
就是比授权码模式少了一步授权码换取token的步骤,
客户端直接存认证服务器需要的账户密码。
客户端携带账户密码访问认证服务器,直接生成token或jwt返回。
客户端携带这个token访问资源服务器,就可以完成认证授权。
适用于合作企业之间的授权认证。