OAuth三方授权登录
一、OAuth简介
1、OAuth2.0介绍
1.1 介绍
OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,允许用户授权第三方 应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他 们数据的所有内容。OAuth在全世界得到广泛应用,目前的版本是2.0版。
协议特点
- 简单:不管是OAuth服务提供者还是应用开发者,都很易于理解与使用;
- 安全:没有涉及到用户密钥等信息,更安全更灵活;
- 开放:任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth;
1.2 应用场景
-
原生app授权:app登录请求后台接口,为了安全认证,所有请求都带token信息,如果登录验证、 请求后台数据
-
前后端分离单页面应用:前后端分离框架,前端请求后台数据,需要进行oauth2安全认证
-
第三方应用授权登录,比如QQ,微博,微信的授权登录
1.3 基本概念
OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务提供商"进行交互
-
Resource owner(资源拥有者):拥有该资源的最终用户,他有访问资源的账号密码;
-
Resource server(资源服务器):受保护资源所在的服务器,如果请求包含正确的访问令牌,就可以访问受保护的资源;
-
Client(客户端):请求访问资源的客户端,可以是浏览器、移动设备或者服务器,客户端会携带访问令牌访问资源服务器上的资源;
-
Authorization server(认证服务器):负责认证客户端身份的服务器,如果客户端认证通过,会给客户端发放访问资源服务器的令牌。
1.4 优缺点
优点
-
更安全,客户端不接触用户密码,服务器端更易集中保护
-
广泛传播并被持续采用
-
短寿命和封装的token
-
资源服务器和授权服务器解耦
-
集中式授权,简化客户端
-
HTTP/JSON友好,易于请求和传递token
-
考虑多种客户端架构场景
-
客户可以具有不同的信任级别
缺点
-
协议框架太宽泛,造成各种实现的兼容性和互操作性差
-
不是一个认证协议,本身并不能告诉你任何用户信息
2、OAuth授权模式
2.1 四种授权模式
不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的
-
Authorization Code(授权码模式):正宗的
OAuth2
的授权模式,客户端先将用户导向认证服务器,认证用户成功后获取授权码,然后进行授权,最后根据授权码获取访问令牌; -
Implicit(隐藏式):和授权码模式相比,取消了获取授权码的过程,直接获取访问令牌;
-
Password(密码模式):客户端直接向用户获取用户名和密码,之后向认证服务器获取访问令牌;
-
Client Credentials(客户端凭证模式):客户端直接通过客户端认证(比如client_id和client_secret)从认证服务器获取访问令牌。
一般来说,授权码模式
和密码模式
是两种常用的授权模式
2.2 授权码模式
指应用先申请一个授权码,然后再用这个授权码获取令牌
流程:
-
客户端将用户导向认证服务器的授权页面;
-
用户在认证服务器页面登录并授权;
-
认证服务器返回授权码给客户端;
-
客户端将授权码传递给客户端所在的后端服务(也可以是自己的认证服务器),由后端服务在后端请求认证服务器获取令牌,并返回给客户端。
2.3 密码模式
如果用户信任应用,应用可以直接携带用户的用户名和密码,直接申请令牌
流程:
-
客户端要求用户提供用户名和密码;
-
客户端携带用户名和密码,访问授权服务器;
-
授权服务器验证用户身份之后,直接返回令牌。
二、三方授权登录
1、需求介绍
自研应用需要扩展时,绕不开的就是集成其他社交软件的三方登录,比如微信/QQ/微博/Github等等,而这用到的模式属于OAuth的授权码方式授权,下面我就介绍几种三方授权登录教程,同时给予数据库扩展设计思路
2、第三方授权登录数据库设计
第三方授权登录的时候,第三方的用户信息是存数据库原有的 user 表还是新建一张表呢 ?答案得看具体项目。三方授权登录之后,第三方用户信息一般都会返回用户唯一的标志 **openid **或者 **unionid **或者 id,具体是什么得看第三方,比如 github 的是 id
2.1 直接通过注册的方式保存到数据库
-
如果网站没有注册功能的,直接通过第三方授权登录,授权成功之后,可以直接把第三的用户信息注册保存到自己数据库的 user 表里面。典型的例子就是微信公众号的授权登录。
-
如果网站有注册功能的,也可以通过第三方授权登录,授权成功之后,也可以直接把第三的用户信息注册保存到自己数据库的 user 表里面(但是密码是后端自动生成的,用户也不知道,只能用第三方授权登录),这样子的第三方的用户和原生注册的用户信息都在同一张表了,这种情况得看自己项目的具体情况。
2.2 增加映射表
现实中很多网站都有多种账户登录方式,比如可以用网站的注册 id 登录,还可以用手机号登录,可以用 QQ 登录等等。数据库中都是有映射关系,QQ、手机号等都是映射在网站的注册 id 上。保证不管用什么方式登录,只要去查映射关系,发现是映射在网站注册的哪个 id 上,就让哪个 id 登录成功。
2.3 建立一个 oauth 表
建立一个 oauth 表,一个 id 列,记录对应的用户注册表的 id,然后你有多少个第三方登陆功能,你就建立多少列,记录第三方登陆接口返回的 openid;第三方登陆的时候,通过这个表的记录的 openid 获取 id 信息,如果存在通过 id 读取注册表然后用 session 记录相关信息。不存在就转向用户登陆/注册界面要用户输入本站注册的账户进行 openid 绑定或者新注册账户信息进行绑定。
3、数据库实战举例
-
用户表分为用户基础信息表 + 用户授权信息表;
-
所有和授权相关,都放在用户信息授权表,用户信息表和用户授权表是一对多的关系
用户基础信息表
id | user_name | user_password | user_mobile | state | more |
---|---|---|---|---|---|
用户id | 用户名 | 用户密码 | 手机号码 | 账号状态 | 其他信息 |
用户授权信息表
id | user_id | login_type | openid | access_token |
---|---|---|---|---|
主键id | 用户id | 第三方登录类型(微信/QQ/微博等) | 第三方应用的唯一标识 | 第三方的保存 token |
三、GitHub 登录
1、概述
文档:https://docs.github.com/cn/developers/apps/building-oauth-apps/creating-an-oauth-app
Github的OAuth 授权原理大致如下
-
A网站让用户跳转到 GitHub
-
GitHub 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意"
-
用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码
-
A 网站使用授权码,向 GitHub 请求令牌
-
GitHub 返回令牌
-
A 网站使用令牌,向 GitHub 请求用户数据
2、应用登记
一个应用要求 OAuth 授权,必须先到对方网站登记,让对方知道是谁在请求,所以要先去 GitHub 登记一下(免费)。GitHub的文档
首先访问Authorized OAuth App,填写登记表进行创建(进入 Github 的 Setting 页面,点击 Developer settings,选择OAuth Apps,选择new OAuth App)
注意回调地址要与我们待会写的接口地址匹配,否则会报错,进入应用后就能看见我们应用了,secrets没有的话可以生成,注意保存
-
Client ID
-
Client secrets
3、Github授权登录原理
3.1 请求用户的 GitHub 身份
它会提示用户使用他们可以用于登录和授权您的应用程序的特定帐户
1 | GET https://github.com/login/oauth/authorize |
参数 | 类型 | 描述 |
---|---|---|
client_id | string | 必填。注册时从 GitHub 收到的客户端 ID |
redirect_uri | string | 您的应用程序中的 URL 将在授权后发送用户,和应用一致,不填为应用的回调地址。请参阅下面有关重定向 url的详细信息 |
login | string | 建议用于登录和授权应用程序的特定帐户 |
scope | string | 范围的空格分隔列表。 如果未提供,则 scope 默认为未授权应用程序的任何范围的用户的空列表。 对于已向应用程序授权作用域的用户,不会显示含作用域列表的 OAuth 授权页面。 相反,通过用户向应用程序授权的作用域集,此流程步骤将自动完成。 例如,如果用户已经执行了两次 Web 流,并且已授权一个具有 user 范围的令牌和另一个具有 repo 范围的令牌,则不提供 scope 的第三个 Web 流将收到具有 user 和 repo 范围的令牌 |
state | string | 一个不可猜测的随机字符串。它用于防止跨站点请求伪造攻击 |
allow_signup | string | 在 OAuth 流程期间,是否会为未经身份验证的用户提供注册 GitHub 的选项。默认值为true . false 在政策禁止注册时使用 |
3.2 用户被 GitHub 重定向回站点
如果用户接受您的请求,GitHub 将重定向回您的站点,其中包含一个临时code
的代码参数以及您在上一步中提供的state
参数状态。临时代码将在 10 分钟后过期。如果状态不匹配,则第三方创建了请求,您应该中止该过程。也就是重回到我们的站点,也就是发送了http://localhost:8080/oauth/githubCallback
(自定义),并且携带了code
将此交换code
为访问令牌OAUTH-TOKEN
1 | POST https://github.com/login/oauth/access_token |
参数 | 类型 | 描述 |
---|---|---|
client_id | string | **必需。**您从 GitHub 收到的 OAuth 应用程序的客户端 ID |
client_secret | string | **必需。**您从 GitHub 收到的 OAuth 应用程序的客户端密码 |
code | string | **必需。**您收到的作为对步骤 1 的响应的代码。 |
redirect_uri | string | 授权后发送用户的应用程序中的 URL |
3.3 使用访问令牌访问API
访问令牌允许代表用户向 API 发出请求,获取用户的基本信息
1 | Authorization: token OAUTH-TOKEN |
4、代码实战
4.1 配置环境
引入依赖
1 | <dependency> |
配置application.yml
1 | github: |
4.2 配置bean类
1 |
|
4.3 配置state工具类
1 |
|
4.4 认证与授权
1 |
|
最后浏览器访问http://localhost:8080/oauth/githubLogin
,即可进入用户授权状态,授权后会进行跳转,自动获取用户的基本信息,后面可以和数据库联动
四、QQ登录
1、概述
大体和Github登录类似,QQ登录OAuth2.0总体处理流程如下
-
申请接入,获取appid和apikey;
-
开发应用,并设置协作者帐号进行测试联调;
-
放置QQ登录按钮;
-
通过用户登录验证和授权,获取Access Token;
-
通过Access Token获取用户的OpenID;
-
调用OpenAPI,来请求访问或修改用户授权的资源。
2、应用创建
首先没有注册的开发者需要先注册并实名,去开发者平台注册并实名,认证通过后进入QQ 互联管理中心,创建一个网站应用新应用(需要先审核个人身份),然后注册应用信息,和 GitHub 的步骤类似
注册后,可以看到应用的 APP ID、APP Key,以及被允许的接口,当然只有一个获取用户信息
3、QQ授权登录原理
3.1 获取Authorization Code
打开浏览器,访问如下地址(请将client_id,redirect_uri,scope等参数值替换为你自己的)
1 | GET https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=[YOUR_APPID]&redirect_uri=[YOUR_REDIRECT_URI]&scope=[THE_SCOPE] |
如果用户点击**“授权并登录”,则成功跳转到指定的redirect_uri**,并跟上Authorization Code(注意此code会在10分钟内过期)
3.2 通过Authorization Code获取Access Token
获取到的access token具有30天有效期,用户再次登录时自动刷新,第三方网站可存储access token信息,以便后续调用OpenAPI访问和修改用户信息时使用
1 | GET https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=[YOUR_APP_ID]&client_secret=[YOUR_APP_Key]&code=[The_AUTHORIZATION_CODE]&redirect_uri=[YOUR_REDIRECT_URI] |
3.3 使用Access Token获取用户信息
发送请求到如下地址,获取用户的OpenID
1 | GET https://graph.qq.com/oauth2.0/me?access_token=YOUR_ACCESS_TOKEN |
使用Access Token以及OpenID来访问和修改用户数据,建议网站在用户登录后,即调用get_user_info接口,获得该用户的头像、昵称并显示在网站上,使用户体验统一。
1 | GET https://graph.qq.com/user/get_user_info?access_token=YOUR_ACCESS_TOKEN&oauth_consumer_key=YOUR_APP_ID&openid=YOUR_OPENID |
4、代码实战
4.1 配置环境
依赖和上面一样,主要配置yml配置文件
1 | qq: |
4.2 配置bean类与工具类
state工具类和上文一样,bean类如下
1 |
|
4.3 认证与授权
qq的比较麻烦,需要实名认证,创建应用也需要备案域名等
1 |
|
五、微信登录
官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
微信的账号创建更加麻烦,需要公司认证,过程和上面方法类似,其他可以参考
Spring Boot + OAuth2.0 实现微信扫码登录,这才叫优雅
参考文章