上一篇:https://blog.csdn.net/LawssssCat/article/details/105336356

Spring Social 官网(旧的):https://projects.spring.io/spring-social/
Spring Social 官方文档:Spring Social Reference

OAuth协议简介

  • OAuth协议要解决的问题
  • OAuth协议中的各种角色
  • OAuth协议运行流程

OAuth 协议要解决的问题

设想:本地平台访问用户在第三方平台上的数据。

如果直接询问用户第三方平台的账号密码会有很多问题:
(假设用户愿意给出第三方平台的账号密码)

  • 本地应用可以访问用户在微信上的所有数据
    (加大本地平台数据的管理成本)
  • 用户只有修改密码,才能收回授权
    (但是,若授权给很多平台,一旦修改密码,其他平台授权也会被收回,加大用户管理授权的成本)
  • 密码泄露的可能性大大提高

<mark>OAuth协议为了解决这个问题诞生的</mark>

(示意图)

OAuth协议规定

  • 访问第三方平台数据不再依靠用户名和密码,而是使用令牌
  • 令牌上可以规定访问数据的权限
  • 令牌上可以设定有效时间

OAuth 协议中的各种角色

三个主角

  • Provider 服务提供商
    <mark>谁提供令牌,谁就是服务提供商</mark>
  • Resource Owner 资源所有者
    用户
  • Client 第三方应用
    希望吧服务提供商的用户(数据)变为自己(可操作)的数据

Provider内部还有 两个角色

  • Authorization Server 认证服务器
    作用是:认证用户的身份,并产生令牌
  • Resource Server 资源服务器
    作用有两:保存用户的资源、验证令牌(最终Client发送临牌是发往Resource Server的)

OAuth 协议运行流程

  1. 用户(Resource Owner)访问第三方应用(Client)
  2. 第三方应用(Client)询问用户(Resource Owner)是否向服务提供商(Provider)发送授权请求
  3. 用户(Resource Owner)同意发送授权请求
  4. 第三方应用(Client)向服务提供商(Provider)的认证服务器(Authorization Server)发送令牌申请请求
  5. 认证服务器(Authorization Server)认证通过后,向第三方应用(Client)发放令牌
  6. 第三方应用(Client)携带令牌,向服务提供商(Provider)的资源服务器(Resource Server)申请资源
  7. 资源服务器(Resource Server)校验令牌无误,开放资源给第三方应用(Client)

同意授权有四种方式

  • 授权码模式(authorization code)
    微信、qq、京东、淘宝。。。大多用此类授权模式

  • 密码模式(resource owner password credentials)

  • 客户端模式(client credentials)

  • 简化模式(implicite)

客户端模式、简化模式不介绍,自己了解

授权码模式详细流程

(下图)如果第三方应用需要用户同意授权,会将用户导向认证服务器


(下图)如果用户同意授权,会将用户导回到第三方应用,<mark>同时携带授权码</mark>
(导去哪里,和导回到哪里,是Client和Provider事先商量好的)

而第三方应用Client得到授权码后,<mark>会携带授权码访问认证服务器,申请令牌</mark>

认证服务器收到Client携带了授权码的令牌申请请求,会校验授权码是否本地之前发出去的授权码,如果是,就发放令牌

为什么叫授权码模式

  • <mark>因为这个模式过程中会产生一个授权码</mark>,这个在其他模式中没有
    (除了简化模式)
  • 其次,用户同意授权的动作是在服务提供商(Provider)上完成的
    (其他模式均是在Client上完成的)

为什么不直接发送令牌
直接发送令牌的模式就是简化模式(implicite),这种模式是给一些简单的仅由脚本支撑的网站做授权用的
(因为那些网站没有服务器,因此不能发送授权码到服务器,只能发送令牌到一个浏览器页面,让浏览器页面上的脚本获取令牌)
所以换而言之,直接发送令牌的模式通过前端脚本也能完成,就容易被XSS攻击
【整理】cookies、攻击(xss、csrf)、防御(stp、sop)、开发(JSONP、WebSockets)

第三方登录(Spring Social 所需要的接口)

续上图,Client 可以通过令牌获取用户信息,并且可以根据用户信息构建认证信息(Authentication)并放入 SecurityContext 中了

(这也是第三方登录的基本原理)

Spring Security 实现第三方登录是通过在过滤链上添加 SocialAuthenticationFilter (下图)
当过滤到第三方登录请求,就引导把上面流程走完

ServiceProvider 接口

ServiceProvider 接口充当服务提供商,通过这个接口的实现,向实现的Provider通信。

SpringSecurity 提供了 AbstractOAuth2ServiceProvider 简化实现配置

这里涉及到 OAuth2,上面讲的所有流程也是基于OAuth2的。
OAuth1国外也有用,如:Twitter、LinkedIn
而国内基本是用OAuth2了。
所以下面就只讲OAuth2了。

OAuthOperations 接口

OAuthOperations包括了OAuth2整个流程的2到5步。
(将用户引导到Provider ⇒ Provider发送令牌)

有一个默认的实现 OAuth2Template

Api 接口

Client 获取 Provider 中用户信息的接口。

因为各种情况都有,因此只提供了 AbstractOAuth2ApiBinding 的抽象实现

Connection、ConnectionFactory接口

  • Connection 封装前面6个流程下来,得到的用户信息
    有一个实现 OAuth2Connection
  • ConnectionFactory 创建 Connection
    有一个实现 OAuth2ConnectionFactory

ApiAdapter 接口

每个服务提供商的用户数据的数据结构是不一样的。
而每个写好的Connection的数据接口是不变的。

<mark>ApiAdapter 做的就是两种数据结构的适配</mark>

UsersConnectionRepository接口和UserConnection数据库表

  • UserConnection数据库表建立Provider用户和Client用户关系的映射。

    如:
    指明Provider服务器上的“张珊”用户,是Client服务器中的“老婆”用户

  • UsersConnectionRepository 用于操作UserConnection表

    实现类 JdebUsersConnectionRepository

Spring Social

官网(旧的):https://projects.spring.io/spring-social/

2018年7月,随着 Spreing Security 5 的发布和 Spring Social Api 接口实现的臃肿,Spring Social最终被废弃,功能被合并到中Spring Security 5 中。
参考:Spring Social End of Life Announcement
但作为学习OAuth2还是有一定借鉴作用。

参考:Spring Social Modules.

Name Description
spring-social-core 项目核心,包含主干逻辑
Spring Social’s Connect Framework and OAuth client support.
Spring Social Facebook 连接 Facebook 的已经写好的实现
Spring Social Twitter
Spring Social LinkedIn
Spring Social GitHub
Spring Social TripIt

(旧的)官网中还能看到其他的基于 Spring Social Core 做的一些实现

可以看到,这里已经有微博(weibo)的实现,而没有QQ、微信的实现。
所以下面就来实现QQ和微信的第三方登录
侧重点

  • QQ:OAuth实现相对标准,重点掌握OAuth实现的流程
  • 微信:跟标准OAuth实现有区别,重点在不同点的细节上