一、导学
Spring Social 主要是用于处理第三方认证。
1. OAuth 2协议 介绍:
角色介绍 :
资源所有者(用户):主要指的就是用户。
第三方应用:比如微信里的小程序。
服务提供商:包含认证服务器和资源服务器。认证服务器主要作用是用来认证用户,资源服务器 主要储存用户的信息。比如微信就是一个服务提供商。
认证流程 :
第一步:用户访问第三方应用。比如,我访问微信上的麦当劳小程序,麦当劳小程序就是第三方应用。
第二步:第三方应用向用户请求授权。比如,麦当劳小程序想要我给它授权。
第三步:用户同意授权给第三方应用。比如,我同意授权给麦当劳小程序。
第四步:第三方应用向服务提供商的认证服务器申请令牌(Token)。比如,麦当劳向微信申请令牌。令牌中包括权限、过期时间等信息。
第五步:用户同意,认证服务器向第三方应用发放令牌(Token)。比如,微信(认证服务器)向麦当劳小程序发放令牌。
第六步:第三方应用使用刚才拿到令牌(Token)的向资源服务器申请使用资源。比如,麦当劳小程序向微信的资源服务器申请使用用户的微信头像和昵称。
第七步:资源服务器通过验证令牌(Token),允许第三方应用使用资源(能使用的资源和时间视令牌中规定的权限而定)。比如,微信验证麦当劳小程序的令牌,验证通过,允许麦当劳小程序使用用户的微信头像和昵称。
授权模式 :
OAuth协议的四种授权模式:授权码模式、简化模式、密码模式、客户端模式
授权码模式:是目前各大互联网厂商主要采用的模式,微信、微博、谷歌等。
其原理如下图:
为什么都采用授权码模式呢?
1.用户同意授权的动作,发生在服务提供商,而不是在第三方应用。安全性更高
2.用户同时授权时,认证服务器返回给第三方应用的是授权码而不是令牌(Token),这就要求第三方应用必须要有一个自己的服务器,令牌(Token)只会发给第三方应用的服务器,而不会发到浏览器上。安全性更高
二、Spring Social 开发:
1. Spring Social 原理:
基本就是OAuth授权码模式的实现。
2. 开发 QQ登录:
1. QQUserInfo 实体:此实体包含了QQ用户信息,具体字段来源于QQ互联(http://wiki.connect.qq.com/get_user_info), 具体字段如下(部分字段):
2. QQ 接口及其实现:QQ接口只有一个方法,就是获取QQ用户信息(昵称、性别、头像等)。QQ接口的实现类 QQImpl要继承 Spring Social的 AbstractOAuth2ApiBinding类,在此类的构造函数中,通过accessToken,调用QQ官方接口 https://graph.qq.com/oauth2.0/me 拿到用户的openId(用户的ID,与QQ号码一一对应)。然后通过accessToken、appId和openId调用QQ官方接口 https://graph.qq.com/user/get_user_info ,获取用户信息。代码如下:
注:在QQImpl的构造函数中,第一行代码
super(accessToken,TokenStrategy.ACCESS_TOKEN_PARAMETER);,它会调用父类的 构造函数将accessToken,设置在父类的RestTemplate上,这样使用父类的RestTemplate发 起Http请求时,就会自动把accessToken参数映射到access_token上。
3. QQServiceProvider:
注:我们自己的QQServiceProvider需要继承 Spring Social的 AbstractOAuth2ServiceProvider,并且此类的泛型是我们自己定义的QQ接口。
3. Session 管理:
主要问题:
1. Session 过期跳转:
2. Session 并发控制:
3. Session 集群处理:
在做集群session存储时,多选用Redis,一是session会频繁读取,而Redis在此方面性能较好。二是Redis自带过期时间,session也存在过期时间,在此方面不谋而合。
3.1 思路:假设我们有两台服务器(localhost:8080、localhost:8081)对外提供登录服务,用户一旦在某一台服务器提供的登录服务上登录成功后,其他机器也应该知晓该用户处于已登录状态,允许用户正常访问服务。在单体服务器上,session是存在于服务器(Tomcat等)上的,其他服务器并不能获取。所以为了实现服务器间共享session,我们需要将用户的session抽离出来,放在Redis上,让多台服务器连接同一个Redis,达成共享session的目的。
3.2 步骤:
1.引入Jar包:本项目架构为spring boot 2.1.3 故引入一下两个jar包(之前引入spring-session 1.3.1有问题,故不建议引入)
2. application.properties 配置:
3. config类 配置:
注:只要完成上述3个步骤的配置,就能完成共享session的功能。
4. 退出登录:
注:没什么可说的,代码如下: