mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
OAuth2.0文档
This commit is contained in:
parent
6d44299902
commit
de7ccf05aa
16
README.md
16
README.md
@ -25,13 +25,11 @@
|
||||
- [开源不易,求鼓励,点个star吧 !](###)
|
||||
|
||||
|
||||
## Sa-Token 是什么?
|
||||
## Sa-Token 介绍
|
||||
Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题
|
||||
|
||||
框架集成简单、开箱即用、API设计清爽,通过Sa-Token,你将以一种极其简单的方式实现系统的权限认证部分
|
||||
|
||||
## Sa-Token 能做什么?
|
||||
|
||||
- **登录验证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
|
||||
- **权限验证** —— 权限认证、角色认证、会话二级认证
|
||||
- **Session会话** —— 全端共享Session、单端独享Session、自定义Session
|
||||
@ -61,7 +59,7 @@ Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证
|
||||
- **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
|
||||
|
||||
##### Sa-Token 功能结构图
|
||||

|
||||

|
||||
|
||||
##### Sa-Token 认证流程图
|
||||

|
||||
@ -92,6 +90,16 @@ Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证
|
||||
6. 高可定制:Sa-Token-SSO模块对代码架构侵入性极低,结合Sa-Token本身的路由拦截特性,你可以非常轻松的定制化开发
|
||||
|
||||
|
||||
## Sa-Token-OAuth2.0 授权登录
|
||||
Sa-OAuth2 模块基于 [RFC-6749 标准](https://tools.ietf.org/html/rfc6749) 编写,通过Sa-OAuth2你可以非常轻松的实现系统的OAuth2.0授权认证
|
||||
|
||||
1. 授权码(Authorization Code):OAuth2.0标准授权步骤,Server端向Client端下放Code码,Client端再用Code码换取授权Token
|
||||
2. 隐藏式(Implicit):无法使用授权码模式时的备用选择,Server端使用URL重定向方式直接将Token下放到Client端页面
|
||||
3. 密码式(Password):Client直接拿着用户的账号密码换取授权Token
|
||||
4. 客户端凭证(Client Credentials):Server端针对Client级别的Token,代表应用自身的资源授权
|
||||
|
||||
详细参考文档:[http://sa-token.dev33.cn/doc/index.html#/oauth2/readme](http://sa-token.dev33.cn/doc/index.html#/oauth2/readme)
|
||||
|
||||
|
||||
## 代码示例
|
||||
|
||||
|
@ -258,13 +258,10 @@ public class StpLogic {
|
||||
tokenValue = createTokenValue(id);
|
||||
}
|
||||
|
||||
// ------ 3. 获取[User-Session] (如果还没有创建session, 则新建, 如果已经创建,则续期)
|
||||
SaSession session = getSessionByLoginId(id, false);
|
||||
if(session == null) {
|
||||
session = getSessionByLoginId(id);
|
||||
} else {
|
||||
// ------ 3. 获取[User-Session], 续期
|
||||
SaSession session = getSessionByLoginId(id, true);
|
||||
session.updateMinTimeout(loginModel.getTimeout());
|
||||
}
|
||||
|
||||
// 在session上记录token签名
|
||||
session.addTokenSign(new TokenSign(tokenValue, loginModel.getDevice()));
|
||||
|
||||
|
@ -111,6 +111,9 @@ public class SaTokenJwtUtil {
|
||||
System.err.println(warn);
|
||||
}
|
||||
|
||||
// 提前调用一下方法,促使其属性初始化
|
||||
StpUtil.getLoginType();
|
||||
|
||||
// 修改默认实现
|
||||
StpUtil.stpLogic = new StpLogic("login") {
|
||||
|
||||
|
@ -3,9 +3,8 @@ package com.pj;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
/**
|
||||
* 启动:OAuth2-Client端
|
||||
* 启动:Sa-OAuth2 ClientServer端
|
||||
* @author kong
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ -16,7 +15,8 @@ public class SaOAuth2ClientApplication {
|
||||
System.out.println("\nSa-Token-OAuth Client端启动成功\n\n" + str);
|
||||
}
|
||||
|
||||
static String str = "首先在host文件 (C:\\WINDOWS\\system32\\drivers\\etc\\hosts) 添加以下内容: \r\n" +
|
||||
static String str = "-------------------- Sa-Token-OAuth2 示例 --------------------\n\n" +
|
||||
"首先在host文件 (C:\\windows\\system32\\drivers\\etc\\hosts) 添加以下内容: \r\n" +
|
||||
" 127.0.0.1 sa-oauth-server.com \r\n" +
|
||||
" 127.0.0.1 sa-oauth-client.com \r\n" +
|
||||
"再从浏览器访问:\r\n" +
|
||||
|
@ -4,7 +4,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 启动:OAuth2-Server端
|
||||
* 启动:Sa-OAuth2 Server端
|
||||
* @author kong
|
||||
*/
|
||||
@SpringBootApplication
|
||||
|
@ -28,7 +28,7 @@ public class SaOAuth2ServerController {
|
||||
// 处理所有OAuth相关请求
|
||||
@RequestMapping("/oauth2/*")
|
||||
public Object request() {
|
||||
System.out.println("--------------进入请求 ");
|
||||
System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());
|
||||
return SaOAuth2Handle.serverRequest();
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- springboot依赖 -->
|
||||
<!-- SpringBoot依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
@ -38,27 +38,27 @@
|
||||
<version>${sa-token-version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token整合redis (使用jdk默认序列化方式) -->
|
||||
<!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
|
||||
<!-- <dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dao-redis</artifactId>
|
||||
<version>${sa-token-version}</version>
|
||||
</dependency> -->
|
||||
|
||||
<!-- sa-token整合redis (使用jackson序列化方式) -->
|
||||
<!-- Sa-Token整合 Redis (使用jackson序列化方式) -->
|
||||
<!-- <dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
||||
<version>${sa-token-version}</version>
|
||||
</dependency> -->
|
||||
|
||||
<!-- 提供redis连接池 -->
|
||||
<!-- 提供Redis连接池 -->
|
||||
<!-- <dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency> -->
|
||||
|
||||
<!-- sa-token整合SpringAOP实现注解鉴权 -->
|
||||
<!-- Sa-Token整合SpringAOP实现注解鉴权 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-aop</artifactId>
|
||||
|
@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pj.satoken.at.StpUserUtil;
|
||||
import com.pj.util.AjaxJson;
|
||||
import com.pj.util.Ttime;
|
||||
|
||||
@ -242,7 +241,6 @@ public class TestController {
|
||||
@RequestMapping("test")
|
||||
public AjaxJson test() {
|
||||
System.out.println("进来了");
|
||||
StpUserUtil.login(10001);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ sa-token:
|
||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
activity-timeout: -1
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
is-concurrent: false
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: true
|
||||
# token风格
|
||||
|
@ -25,13 +25,11 @@
|
||||
- [开源不易,求鼓励,点个star吧 !](###)
|
||||
|
||||
|
||||
## Sa-Token 是什么?
|
||||
## Sa-Token 介绍
|
||||
Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题
|
||||
|
||||
框架集成简单、开箱即用、API设计清爽,通过Sa-Token,你将以一种极其简单的方式实现系统的权限认证部分
|
||||
|
||||
## Sa-Token 能做什么?
|
||||
|
||||
- **登录验证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
|
||||
- **权限验证** —— 权限认证、角色认证、会话二级认证
|
||||
- **Session会话** —— 全端共享Session、单端独享Session、自定义Session
|
||||
@ -61,7 +59,7 @@ Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证
|
||||
- **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
|
||||
|
||||
##### Sa-Token 功能结构图
|
||||

|
||||

|
||||
|
||||
##### Sa-Token 认证流程图
|
||||

|
||||
@ -92,6 +90,16 @@ Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证
|
||||
6. 高可定制:Sa-Token-SSO模块对代码架构侵入性极低,结合Sa-Token本身的路由拦截特性,你可以非常轻松的定制化开发
|
||||
|
||||
|
||||
## Sa-Token-OAuth2.0 授权登录
|
||||
Sa-OAuth2 模块基于 [RFC-6749 标准](https://tools.ietf.org/html/rfc6749) 编写,通过Sa-OAuth2你可以非常轻松的实现系统的OAuth2.0授权认证
|
||||
|
||||
1. 授权码(Authorization Code):OAuth2.0标准授权步骤,Server端向Client端下放Code码,Client端再用Code码换取授权Token
|
||||
2. 隐藏式(Implicit):无法使用授权码模式时的备用选择,Server端使用URL重定向方式直接将Token下放到Client端页面
|
||||
3. 密码式(Password):Client直接拿着用户的账号密码换取授权Token
|
||||
4. 客户端凭证(Client Credentials):Server端针对Client级别的Token,代表应用自身的资源授权
|
||||
|
||||
详细参考文档:[http://sa-token.dev33.cn/doc/index.html#/oauth2/readme](http://sa-token.dev33.cn/doc/index.html#/oauth2/readme)
|
||||
|
||||
|
||||
## 代码示例
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
- **进阶**
|
||||
- [全局过滤器](/use/global-filter)
|
||||
- [集群、分布式](/senior/dcs)
|
||||
<!-- - [单点登录](/senior/sso) -->
|
||||
- [多账号验证](/use/many-account)
|
||||
|
||||
- **单点登录**
|
||||
@ -40,6 +39,11 @@
|
||||
- [SSO模式二 URL重定向传播会话](/sso/sso-type2)
|
||||
- [SSO模式三 Http请求获取会话](/sso/sso-type3)
|
||||
|
||||
- **OAuth2.0**
|
||||
- [OAuth2.0简述](/oauth2/readme)
|
||||
- [OAuth2-Server搭建](/oauth2/oauth2-server)
|
||||
- [OAuth2-API列表](/oauth2/oauth2-api)
|
||||
|
||||
- **插件**
|
||||
- [AOP注解鉴权](/plugin/aop-at)
|
||||
- [临时Token验证](/plugin/temp-token)
|
||||
|
@ -70,6 +70,9 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
|
||||
/* yml语言样式优化 */
|
||||
.main-box .lang-yml{color: #01A252 !important; opacity: 1;}
|
||||
|
||||
/* yml语言样式优化 */
|
||||
.main-box .lang-url{color: #E96917 !important; opacity: 1;}
|
||||
|
||||
/* js语言样式优化 */
|
||||
.main-box .lang-js{color: #01a252 !important;}
|
||||
.lang-js .token.comment{color: #CDAB53;}
|
||||
|
233
sa-token-doc/doc/oauth2/oauth2-api.md
Normal file
233
sa-token-doc/doc/oauth2/oauth2-api.md
Normal file
@ -0,0 +1,233 @@
|
||||
# Sa-Token-OAuth2 Server端 API列表
|
||||
基于官方仓库的搭建示例,`OAuth2-Server`端会暴露出以下API,`OAuth2-Client`端可据此文档进行对接
|
||||
|
||||
---
|
||||
|
||||
## 1、模式一:授权码(Authorization Code)
|
||||
|
||||
### 1.1、获取授权码
|
||||
|
||||
根据以下格式构建URL,引导用户访问 (复制时请注意删减掉相应空格和换行符)
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/authorize
|
||||
?response_type=code
|
||||
&client_id={value}
|
||||
&redirect_uri={value}
|
||||
&scope={value}
|
||||
$state={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| response_type | 是 | 返回类型,这里请填写:code |
|
||||
| client_id | 是 | 应用id |
|
||||
| redirect_uri | 是 | 用户确认授权后,重定向的url地址 |
|
||||
| scope | 否 | 具体请求的权限,多个用逗号隔开 |
|
||||
| state | 否 | 随机值,此参数会在重定向时追加到url末尾,不填不追加 |
|
||||
|
||||
注意点:
|
||||
1. 如果用户在Server端尚未登录:会被转发到登录视图,你可以参照文档或官方示例自定义登录页面
|
||||
2. 如果scope参数为空,或者请求的权限用户近期已确认过,则无需用户再次确认,达到静默授权的效果,否则需要用户手动确认,服务器才可以下放code授权码
|
||||
|
||||
用户确认授权之后,会被重定向至`redirect_uri`,并追加code参数与state参数,形如:
|
||||
``` url
|
||||
redirect_uri?code={code}&state={state}
|
||||
```
|
||||
|
||||
Code授权码具有以下特点:
|
||||
1. 每次授权产生的Code码都不一样
|
||||
2. Code码用完即废,不能二次使用
|
||||
3. 一个Code的有效期默认为五分钟,超时自动作废
|
||||
4. 每次授权产生新Code码,会导致旧Code码立即作废,即使旧Code码尚未使用
|
||||
|
||||
|
||||
### 1.2、根据授权码获取Access-Token
|
||||
获得Code码后,我们可以通过以下接口,获取到用户的`Access-Token`、`Refresh-Token`、`openid`等关键信息
|
||||
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/token
|
||||
?grant_type=authorization_code
|
||||
&client_id={value}
|
||||
&client_secret={value}
|
||||
&code={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| grant_type | 是 | 授权类型,这里请填写:authorization_code |
|
||||
| client_id | 是 | 应用id |
|
||||
| client_secret | 是 | 应用秘钥 |
|
||||
| code | 是 | 步骤1.1中获取到的授权码 |
|
||||
|
||||
接口返回示例:
|
||||
|
||||
``` js
|
||||
{
|
||||
"code": 200, // 200表示请求成功,非200标识请求失败, 以下不再赘述
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"access_token": "7Ngo1Igg6rieWwAmWMe4cxT7j8o46mjyuabuwLETuAoN6JpPzPO2i3PVpEVJ", // Access-Token值
|
||||
"refresh_token": "ZMG7QbuCVtCIn1FAJuDbgEjsoXt5Kqzii9zsPeyahAmoir893ARA4rbmeR66", // Refresh-Token值
|
||||
"expires_in": 7199, // Access-Token剩余有效期,单位秒
|
||||
"refresh_expires_in": 2591999, // Refresh-Token剩余有效期,单位秒
|
||||
"client_id": "1001", // 应用id
|
||||
"scope": "userinfo", // 此令牌包含的权限
|
||||
"openid": "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__" // openid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 1.3、根据 Refresh-Token 刷新 Access-Token (如果需要的话)
|
||||
Access-Token的有效期较短,如果每次过期都需要重新授权的话,会比较影响用户体验,因此我们可以在后台通过`Refresh-Token` 刷新 `Access-Token`
|
||||
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/refresh
|
||||
?grant_type=refresh_token
|
||||
&client_id={value}
|
||||
&client_secret={value}
|
||||
&refresh_token={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| grant_type | 是 | 授权类型,这里请填写:refresh_token |
|
||||
| client_id | 是 | 应用id |
|
||||
| client_secret | 是 | 应用秘钥 |
|
||||
| refresh_token | 是 | 步骤1.2中获取到的`Refresh-Token`值 |
|
||||
|
||||
接口返回值同章节1.2,此处不再赘述
|
||||
|
||||
|
||||
### 1.4、根据 Access-Token 获取相应用户的账号信息
|
||||
注:此接口为官方仓库模拟接口,正式项目中大家可以根据此样例,自定义需要的接口及参数
|
||||
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/userinfo?access_token={value}
|
||||
```
|
||||
|
||||
返回值样例:
|
||||
``` js
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"nickname": "shengzhang_", // 账号昵称
|
||||
"avatar": "http://xxx.com/1.jpg", // 头像地址
|
||||
"age": "18", // 年龄
|
||||
"sex": "男", // 性别
|
||||
"address": "山东省 青岛市 城阳区" // 所在城市
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 2、模式二:隐藏式(Implicit)
|
||||
|
||||
根据以下格式构建URL,引导用户访问:
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/authorize
|
||||
?response_type=token
|
||||
&client_id={value}
|
||||
&redirect_uri={value}
|
||||
&scope={value}
|
||||
$state={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| response_type | 是 | 返回类型,这里请填写:token |
|
||||
| client_id | 是 | 应用id |
|
||||
| redirect_uri | 是 | 用户确认授权后,重定向的url地址 |
|
||||
| scope | 否 | 具体请求的权限,多个用逗号隔开 |
|
||||
| state | 否 | 随机值,此参数会在重定向时追加到url末尾,不填不追加 |
|
||||
|
||||
此模式会越过授权码的步骤,直接返回Access-Token到前端页面,形如:
|
||||
``` url
|
||||
redirect_uri#token=xxxx-xxxx-xxxx-xxxx
|
||||
```
|
||||
|
||||
## 3、模式三:密码式(Password)
|
||||
首先在Client端构建表单,让用户输入Server端的账号和密码,然后在Client端访问接口
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/token
|
||||
?grant_type=password
|
||||
&client_id={value}
|
||||
&username={value}
|
||||
&password={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| grant_type| 是 | 返回类型,这里请填写:password|
|
||||
| client_id | 是 | 应用id |
|
||||
| username | 是 | 用户的Server端账号 |
|
||||
| password | 否 | 用户的Server端密码 |
|
||||
|
||||
接口返回示例:
|
||||
|
||||
``` js
|
||||
{
|
||||
"code": 200, // 200表示请求成功,非200标识请求失败, 以下不再赘述
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"access_token": "7Ngo1Igg6rieWwAmWMe4cxT7j8o46mjyuabuwLETuAoN6JpPzPO2i3PVpEVJ", // Access-Token值
|
||||
"refresh_token": "ZMG7QbuCVtCIn1FAJuDbgEjsoXt5Kqzii9zsPeyahAmoir893ARA4rbmeR66", // Refresh-Token值
|
||||
"expires_in": 7199, // Access-Token剩余有效期,单位秒
|
||||
"refresh_expires_in": 2591999, // Refresh-Token剩余有效期,单位秒
|
||||
"client_id": "1001", // 应用id
|
||||
"scope": "", // 此令牌包含的权限
|
||||
"openid": "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__" // openid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 4、模式四:凭证式(Client Credentials)
|
||||
以上三种模式获取的都是用户的 `Access-Token`,代表用户对第三方应用的授权,
|
||||
在OAuth2.0中还有一种针对 Client级别的授权, 即:`Client-Token`,代表应用自身的资源授权
|
||||
|
||||
在Client端的后台访问以下接口:
|
||||
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/client_token
|
||||
?grant_type=client_credentials
|
||||
&client_id={value}
|
||||
&client_secret={value}
|
||||
```
|
||||
|
||||
参数详解:
|
||||
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| grant_type | 是 | 返回类型,这里请填写:client_credentials|
|
||||
| client_id | 是 | 应用id |
|
||||
| client_secret | 是 | 应用秘钥 |
|
||||
|
||||
接口返回值样例:
|
||||
``` js
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"client_token": "HmzPtaNuIqGrOdudWLzKJRSfPadN497qEJtanYwE7ZvHQWDy0jeoZJuDIiqO", // Client-Token 值
|
||||
"expires_in": 7199, // Token剩余有效时间,单位秒
|
||||
"client_id": "1001", // 应用id
|
||||
"scope": null // 包含权限
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
注:`Client-Token`具有延迟作废特性,即:在每次获取最新`Client-Token`的时候,旧`Client-Token`不会立即过期,而是作为`Past-Token`再次储存起来,
|
||||
资源请求方只要携带其中之一便可通过Token校验,这种特性保证了在大量并发请求时不会出现“新旧Token交替造成的授权失效”, 保证了服务的高可用
|
||||
|
178
sa-token-doc/doc/oauth2/oauth2-server.md
Normal file
178
sa-token-doc/doc/oauth2/oauth2-server.md
Normal file
@ -0,0 +1,178 @@
|
||||
# 搭建OAuth2-Server
|
||||
|
||||
---
|
||||
|
||||
### 1、准备工作
|
||||
首先修改hosts文件`(C:\windows\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
|
||||
``` url
|
||||
127.0.0.1 sa-oauth-server.com
|
||||
127.0.0.1 sa-oauth-client.com
|
||||
```
|
||||
|
||||
|
||||
### 2、引入依赖
|
||||
创建SpringBoot项目 `sa-token-demo-oauth2-server`(不会的同学自行百度或参考仓库示例),添加pom依赖:
|
||||
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>${sa.top.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token-OAuth2.0 模块 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<version>${sa.top.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 3、开放服务
|
||||
1、新建 `SaOAuth2TemplateImpl`
|
||||
``` java
|
||||
/**
|
||||
* Sa-Token OAuth2.0 整合实现
|
||||
*/
|
||||
@Component
|
||||
public class SaOAuth2TemplateImpl extends SaOAuth2Template {
|
||||
|
||||
// 根据 id 获取 Client 信息
|
||||
@Override
|
||||
public SaClientModel getClientModel(String clientId) {
|
||||
// 此为模拟数据,真实环境需要从数据库查询
|
||||
if("1001".equals(clientId)) {
|
||||
return new SaClientModel()
|
||||
.setClientId("10001")
|
||||
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
|
||||
.setAllowUrl("*")
|
||||
.setContractScope("userinfo");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 根据ClientId 和 LoginId 获取openid
|
||||
@Override
|
||||
public String getOpenid(String clientId, Object loginId) {
|
||||
// 此为模拟数据,真实环境需要从数据库查询
|
||||
return "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__";
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
2、新建`SaOAuth2ServerController`
|
||||
``` java
|
||||
/**
|
||||
* Sa-OAuth2 Server端 控制器
|
||||
*/
|
||||
@RestController
|
||||
public class SaOAuth2ServerController {
|
||||
|
||||
// 处理所有OAuth相关请求
|
||||
@RequestMapping("/oauth2/*")
|
||||
public Object request() {
|
||||
System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());
|
||||
return SaOAuth2Handle.serverRequest();
|
||||
}
|
||||
|
||||
// Sa-OAuth2 定制化配置
|
||||
@Autowired
|
||||
public void setSaOAuth2Config(SaOAuth2Config cfg) {
|
||||
cfg.
|
||||
// 配置:未登录时返回的View
|
||||
setNotLoginView(() -> {
|
||||
String msg = "当前会话在SSO-Server端尚未登录,请先访问"
|
||||
+ "<a href='/oauth2/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
|
||||
+ "进行登录之后,刷新页面开始授权";
|
||||
return msg;
|
||||
}).
|
||||
// 配置:登录处理函数
|
||||
setDoLoginHandle((name, pwd) -> {
|
||||
if("sa".equals(name) && "123456".equals(pwd)) {
|
||||
StpUtil.login(10001);
|
||||
return SaResult.ok();
|
||||
}
|
||||
return SaResult.error("账号名或密码错误");
|
||||
}).
|
||||
// 配置:确认授权时返回的View
|
||||
setConfirmView((clientId, scope) -> {
|
||||
String msg = "<p>应用 " + clientId + " 请求授权:" + scope + "</p>"
|
||||
+ "<p>请确认:<a href='/oauth2/doConfirm?client_id=" + clientId + "&scope=" + scope + "' target='_blank'> 确认授权 </a></p>"
|
||||
+ "<p>确认之后刷新页面</p>";
|
||||
return msg;
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
// 全局异常拦截
|
||||
@ExceptionHandler
|
||||
public SaResult handlerException(Exception e) {
|
||||
e.printStackTrace();
|
||||
return SaResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
注意:在`setDoLoginHandle`函数里如果要获取name, pwd以外的参数,可通过`SaHolder.getRequest().getParam("xxx")`来获取
|
||||
|
||||
3、创建启动类:
|
||||
``` java
|
||||
/**
|
||||
* 启动:Sa-OAuth2 Server端
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class SaOAuth2ServerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SaOAuth2ServerApplication.class, args);
|
||||
System.out.println("\nSa-Token-OAuth Server端启动成功");
|
||||
}
|
||||
}
|
||||
```
|
||||
启动项目
|
||||
|
||||
|
||||
### 4、访问测试
|
||||
|
||||
1、由于暂未搭建Client端,我们可以使用Sa-Token官网作为重定向URL进行测试:
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/authorize?response_type=code&client_id=1001&redirect_uri=http://sa-token.dev33.cn/&scope=userinfo
|
||||
```
|
||||
|
||||
2、由于首次访问,我们在OAuth-Server端暂未登录,会被转发到登录视图
|
||||
|
||||

|
||||
|
||||
3、点击doLogin进行登录之后刷新页面,会提示我们确认授权
|
||||

|
||||
|
||||
4、点击确认授权之后刷新页面,我们会被重定向至 redirect_uri 页面,并携带了code参数
|
||||
|
||||

|
||||
|
||||
4、我们拿着code参数,访问以下地址:
|
||||
``` url
|
||||
http://sa-oauth-server.com:8001/oauth2/token?grant_type=authorization_code&client_id=1001&client_secret=aaaa-bbbb-cccc-dddd-eeee&code={code}
|
||||
```
|
||||
|
||||
将得到 `Access-Token`、`Refresh-Token`、`openid`等授权信息
|
||||
|
||||

|
||||
|
||||
测试完毕
|
||||
|
||||
|
||||
### 5、运行官方示例
|
||||
以上代码只是简单模拟了一下OAuth2.0的授权流程,现在,我们运行一下官方示例,里面有制作好的UI界面
|
||||
|
||||
- OAuth2-Server端: `/sa-token-demo/sa-token-demo-oauth2-server/` [源码链接](https://gitee.com/dromara/sa-token/tree/dev/sa-token-demo/sa-token-demo-oauth2-server) <br/>
|
||||
- OAuth2-Client端: `/sa-token-demo/sa-token-demo-oauth2-client/` [源码链接](https://gitee.com/dromara/sa-token/tree/dev/sa-token-demo/sa-token-demo-oauth2-client) <br/>
|
||||
|
||||
依次启动`OAuth2-Server` 与 `OAuth2-Client`,然后从浏览器访问:[http://sa-oauth-client.com:8002](http://sa-oauth-client.com:8002)
|
||||
|
||||

|
||||
|
||||
如图,可以针对OAuth2.0四种模式进行详细测试
|
||||
|
||||
|
31
sa-token-doc/doc/oauth2/readme.md
Normal file
31
sa-token-doc/doc/oauth2/readme.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Sa-Token-OAuth2.0 模块
|
||||
|
||||
---
|
||||
|
||||
### 什么是OAuth2.0?解决什么问题?
|
||||
|
||||
简单来讲,OAuth2.0的应用场景可以理解为单点登录的升级版,单点登录解决了多个系统间会话的共享,OAuth2.0在此基础上增加了应用之间的权限控制
|
||||
(SO:有些系统采用OAuth2.0模式实现了单点登录,但这总给人一种“杀鸡焉用宰牛刀”的感觉)
|
||||
|
||||
有关OAuth2.0的设计思想网上教程较多,此处不再重复赘述,详细可参考博客:
|
||||
[OAuth2.0 简单解释](https://www.ruanyifeng.com/blog/2019/04/oauth_design.html)
|
||||
<!-- 、[OAuth2.0 的四种方式](http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html) -->
|
||||
|
||||
Sa-OAuth2 模块基于 [RFC-6749 标准](https://tools.ietf.org/html/rfc6749) 编写,通过Sa-OAuth2你可以非常轻松的实现系统的OAuth2.0授权认证
|
||||
|
||||
|
||||
### OAuth2.0 四种模式
|
||||
|
||||
基于不同的使用场景,OAuth2.0设计了四种模式:
|
||||
|
||||
1. 授权码(Authorization Code):OAuth2.0标准授权步骤,Server端向Client端下放Code码,Client端再用Code码换取授权Token
|
||||
2. 隐藏式(Implicit):无法使用授权码模式时的备用选择,Server端使用URL重定向方式直接将Token下放到Client端页面
|
||||
3. 密码式(Password):Client直接拿着用户的账号密码换取授权Token
|
||||
4. 客户端凭证(Client Credentials):Server端针对Client级别的Token,代表应用自身的资源授权
|
||||
|
||||

|
||||
|
||||
接下来我们将通过简单示例演示如何在Sa-OAuth2中完成这四种模式的对接: [搭建OAuth2-Server](/oauth2/oauth2-server)
|
||||
|
||||
|
||||
|
@ -40,8 +40,8 @@ OK,所有理论就绪,下面开始实战
|
||||
Sa-Token整合同域下的单点登录非常简单,相比于正常的登录,你只需要在配置文件中增加配置 `sa-token.cookie-domain=xxx.com` 来指定一下Cookie写入时指定的父级域名即可,详细步骤示例如下:
|
||||
|
||||
#### 1. 准备工作
|
||||
首先修改hosts文件(`C:\WINDOWS\system32\drivers\etc\hosts`),添加以下IP映射,方便我们进行测试:
|
||||
``` text
|
||||
首先修改hosts文件(`C:\windows\system32\drivers\etc\hosts`),添加以下IP映射,方便我们进行测试:
|
||||
``` url
|
||||
127.0.0.1 s1.stp.com
|
||||
127.0.0.1 s2.stp.com
|
||||
127.0.0.1 s3.stp.com
|
||||
|
@ -29,8 +29,8 @@ OK,所有理论就绪,下面开始实战
|
||||
|
||||
### 1、准备工作
|
||||
|
||||
首先修改hosts文件`(C:\WINDOWS\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
|
||||
``` text
|
||||
首先修改hosts文件`(C:\windows\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
|
||||
``` url
|
||||
127.0.0.1 s1.stp.com
|
||||
127.0.0.1 s2.stp.com
|
||||
127.0.0.1 s3.stp.com
|
||||
|
@ -94,6 +94,7 @@ public class SsoServerController {
|
||||
|
||||
}
|
||||
```
|
||||
注意:在`setDoLoginHandle`函数里如果要获取name, pwd以外的参数,可通过`SaHolder.getRequest().getParam("xxx")`来获取
|
||||
|
||||
##### 1.4、application.yml配置
|
||||
``` yml
|
||||
@ -243,8 +244,8 @@ public class SaSsoClientApplication {
|
||||
### 3、测试访问
|
||||
|
||||
##### 3.1 修改host文件
|
||||
首先修改hosts文件`(C:\WINDOWS\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
|
||||
```
|
||||
首先修改hosts文件`(C:\windows\system32\drivers\etc\hosts)`,添加以下IP映射,方便我们进行测试:
|
||||
``` url
|
||||
127.0.0.1 sa-sso-server.com
|
||||
127.0.0.1 sa-sso-client1.com
|
||||
127.0.0.1 sa-sso-client2.com
|
||||
|
@ -39,7 +39,7 @@ sa-token:
|
||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
activity-timeout: -1
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
is-concurrent: false
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: false
|
||||
# token风格
|
||||
|
@ -18,9 +18,9 @@ sa-token:
|
||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
activity-timeout: -1
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
is-concurrent: false
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: false
|
||||
is-share: true
|
||||
# token风格
|
||||
token-style: uuid
|
||||
# 是否输出操作日志
|
||||
@ -117,3 +117,31 @@ sa-token:
|
||||
# SSO-Server端 单点登录地址
|
||||
auth-url: http://sa-sso-server.com:9000/sso/auth
|
||||
```
|
||||
|
||||
|
||||
|
||||
### OAuth2.0相关配置
|
||||
| 参数名称 | 类型 | 默认值 | 说明 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| isCode | Boolean | true | 是否打开模式:授权码(Authorization Code) |
|
||||
| isImplicit | Boolean | false | 是否打开模式:隐藏式(Implicit) |
|
||||
| isPassword | Boolean | false | 是否打开模式:密码式(Password) |
|
||||
| isClient | Boolean | false | 是否打开模式:凭证式(Client Credentials) |
|
||||
| isNewRefresh | Boolean | false | 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token |
|
||||
| codeTimeout | long | 300 | Code授权码 保存的时间(单位秒) 默认五分钟 |
|
||||
| accessTokenTimeout | long | 7200 | Access-Token 保存的时间(单位秒) 默认两个小时 |
|
||||
| refreshTokenTimeout | long | 2592000 | Refresh-Token 保存的时间(单位秒) 默认30 天 |
|
||||
| clientTokenTimeout | long | 7200 | Client-Token 保存的时间(单位秒) 默认两个小时 |
|
||||
|
||||
配置示例:
|
||||
``` yml
|
||||
# sa-token配置
|
||||
sa-token:
|
||||
token-name: satoken-server
|
||||
# OAuth2.0 配置
|
||||
oauth2:
|
||||
is-code: true
|
||||
is-implicit: true
|
||||
is-password: true
|
||||
is-client: true
|
||||
```
|
||||
|
@ -87,9 +87,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
}
|
||||
});
|
||||
|
||||
// 提前退出
|
||||
|
||||
|
||||
// 提前退出 (执行SaRouter.stop()后会直接退出匹配链)
|
||||
SaRouter.match("/test/back", () -> SaRouter.stop());
|
||||
|
||||
// 在多账号模式下,可以使用任意StpUtil进行校验
|
||||
SaRouter.match("/user/**", () -> StpUserUtil.checkLogin());
|
||||
|
@ -69,7 +69,7 @@ public class SaOAuth2Template {
|
||||
*/
|
||||
public AccessTokenModel checkAccessToken(String accessToken) {
|
||||
AccessTokenModel at = getAccessToken(accessToken);
|
||||
SaOAuth2Exception.throwBy(at == null, "无效:access_token" + accessToken);
|
||||
SaOAuth2Exception.throwBy(at == null, "无效access_token:" + accessToken);
|
||||
return at;
|
||||
}
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user