OAuth 2.0 学习
一、什么是单点登录
多点登录
传统的多点登录系统中,每个站点都实现了本站专用的帐号数据库和登录模块。各站点的登录状态相互不认可,各站点需要逐一手工登录。 有两个术语含义如下:
- 认证(authentication): 验证用户的身份;
- 授权(authorization): 验证用户的访问权限。
单点登录
单点登录,英文是 Single Sign On,缩写为 SSO。 多个站点共用一台认证授权服务器(用户数据库和认证授权模块共用)。用户经由其中任何一个站点登录后,可以免登录访问其他所有站点。 而且,各站点间可以通过该登录状态直接交互。
二、oauth的运行流程
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
运行流程如下图,摘自RFC 6749。
- (A)用户打开客户端以后,客户端要求用户给予授权。
- (B)用户同意给予客户端授权。
- (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
- (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
- (E)客户端使用令牌,向资源服务器申请获取资源。
- (F)资源服务器确认令牌无误,同意向客户端开放资源。
我们是对内的系统,并不需要那么复杂的流程,所以我们看下oauth的授权模式当中的密码模式:
+----------+
| Resource |
| Owner |
| |
+----------+
v
| Resource Owner
(A) Password Credentials
|
v
+---------+ +---------------+
| |>--(B)---- Resource Owner ------->| |
| | Password Credentials | Authorization |
| Client | | Server |
| |<--(C)---- Access Token ---------<| |
| | (w/ Optional Refresh Token) | |
+---------+ +---------------+
这里的流程相对就比较简单了:
(A)用户向客户端提供用户名和密码。
(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。
(C)认证服务器确认无误后,向客户端提供访问令牌。
现在将简单的转换下思路:
-
Resource Owner
:资源拥有者,拥有订单,购物车等数据的人,既用户 -
Client
:客户端,浏览器 -
Authorization Server
:认证服务器,也就是服务器咯。
在此A、B、C三个流程就变成了:
(A)用户在浏览器输入用户名和密码。
(B)浏览器将用户名和密码发给服务器,向后者请求令牌(token)。
(C)服务器确认无误后,返回token给用户。
三、OAuth 2.0 的四种方式
1)、授权码模式(authorization-code/Auth Code)
授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
应用的场景:成功后跳转其他页面,如第三方微信登录等
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
- 获取code
http://localhost:9090/oauth/authorize?client_id=normal-app&response_type=code&scope=read&redirect_uri=http://139.224.247.139:8080/
- 用code换取token
http://localhost:9090/oauth/token?code=hepL9e&grant_type=authorization_code&client_id=normal-app&redirect_uri=http://139.224.247.139:8080/&client_secret=123456&scope=read
2)、简化模式(implicit)
有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 应用的场景:不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌
3)、密码模式(password credentials)
如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。
应用的场景:web页面用户名密码登录
模拟请求:
post http://localhost:8080/oauth/token?username=user_1&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456
请求正常返回的结果:
{
"access_token": "c2340190-48f3-4291-bb17-1e4d51bcb284",
"token_type": "bearer",
"refresh_token": "03ee113c-a942-452a-9918-7ffe24472a7f",
"expires_in": 40399,
"scope": "select"
}
4)、客户端模式(client credentials)
客户端模式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 应用的场景:主要针对openapi,使用apikey和secretkey方式
post http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456
结果如下
{
"access_token": "05a4e614-f34b-4c83-9ec1-89ea55c0afd2",
"token_type": "bearer",
"expires_in": 40396,
"scope": "select"
}
HttpSecurity中关于successHandler与successForwardUrl的生效:后面的设置会覆盖掉前面的设置
常用接口
检查token有效性
配置的方法:
- 方法一: 在继承AuthorizationServerConfigurerAdapter中的configure的方法中,添加
oauthServer.checkTokenAccess("permitAll()");
- 方法二: 配置文件中配置
security.oauth2.authorization.check-token-access=permitAll()
请求接口示例:
get localhost:9090/oauth/check_token?token=8e9d3088-6c21-414f-b597-5ef64948d9f7
oauth_client_detail表 说明
字段名 | 字段约束 | 详细描述 | 范例 |
---|---|---|---|
client_id | 主键,必须唯一,不能为空 | 用于唯一标识每一个客户端(client);注册时必须填写(也可以服务端自动生成),这个字段是必须的,实际应用也有叫app_key | OaH1heR2E4eGnBr87Br8FHaUFrA2Q0kE8HqZgpdg8Sw |
resource_ids | 不能为空,用逗号分隔 | 客户端能访问的资源id集合,注册客户端时,根据实际需要可选择资源id,也可以根据不同的额注册流程,赋予对应的额资源id | order-resource,pay-resource |
client_secret | 必须填写 | 注册填写或者服务端自动生成,实际应用也有叫app_secret, 必须要有前缀代表加密方式 | {bcrypt}gY/Hauph1tqvVWiH4atxteSH8sRX03IDXRIQi03DVTFGzKfz8ZtGi |
scope | 不能为空,用逗号分隔 | 指定client的权限范围,比如读写权限,比如移动端还是web端权限 | read,write / web,mobile |
authorized_grant_types | 不能为空 | 可选值 授权码模式:authorization_code,密码模式:password,刷新token: refresh_token, 隐式模式: implicit: 客户端模式: client_credentials。支持多个用逗号分隔 | password,refresh_token |
web_server_redirect_uri | 可为空 | 客户端重定向uri,authorization_code和implicit需要该值进行校验,注册时填写, | httt://baidu.com |
authorities | 可为空 | 指定用户的权限范围,如果授权的过程需要用户登陆,该字段不生效,implicit和client_credentials需要 | ROLE_ADMIN,ROLE_USER |
access_token_validity | 可空 | 设置access_token的有效时间(秒),默认(606012,12小时) | 3600 |
refresh_token_validity | 可空 | 设置refresh_token有效期(秒),默认(606024*30, 30填) | 7200 |
additional_information | 可空 | 值必须是json格式 {"key", "value"} | |
autoapprove | false/true/read/write | 默认false,适用于authorization_code模式,设置用户是否自动approval操作,设置true跳过用户确认授权操作页面,直接跳到redirect_uri | false |
博客
SpringCloud鉴权之OAuth2.0(上篇)
https://segmentfault.com/a/1190000019772023
从零开始的Spring Security Oauth2(二)
http://blog.didispace.com/spring-security-oauth2-xjf-2/
OAuth2.0 原理流程及其单点登录和权限控制
https://blog.csdn.net/kefengwang/article/details/81213025
微服务实战(一)基于OAUTH2.0统一认证授权的微服务基础架构
https://blog.csdn.net/w1054993544/article/details/78932614
oauth2.0通过JdbcClientDetailsService从数据库读取相应的配置
https://www.cnblogs.com/charlypage/p/9383420.html
Spring Security OAuth2.0 认证协议【1】- 基本概念
https://blog.csdn.net/LawssssCat/article/details/105065992
Spring boot+Security OAuth2 爬坑日记(2)
https://blog.csdn.net/qq_31063463/article/details/83073739
Spring Cloud OAuth2 实现自定义返回格式
https://segmentfault.com/a/1190000020317220?utm_source=tag-newest
restTemplate基本的认证
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(map.get("client_id").toString(),map.get("client_secret").toString()));
注意:本文归作者所有,未经作者允许,不得转载