docs(oauth2): 优化调整 oauth2 章节相关文档

This commit is contained in:
click33 2025-05-14 04:18:14 +08:00
parent 5b3a64b9fc
commit 3e13a39244
11 changed files with 109 additions and 81 deletions

View File

@ -1,4 +1,4 @@
//package com.pj.oauth2.custom;
//package com.pj.oauth2.custom_grant_type;
//
//import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
//import cn.dev33.satoken.oauth2.granttype.handler.PasswordGrantTypeHandler;

View File

@ -1,4 +1,4 @@
//package com.pj.oauth2.custom;
//package com.pj.oauth2.custom_grant_type;
//
//import cn.dev33.satoken.SaManager;
//import cn.dev33.satoken.context.model.SaRequest;

View File

@ -1,4 +1,4 @@
//package com.pj.oauth2.custom;
//package com.pj.oauth2.custom_grant_type;
//
//import cn.dev33.satoken.SaManager;
//import cn.dev33.satoken.util.SaFoxUtil;

View File

@ -1,4 +1,4 @@
//package com.pj.oauth2.custom;
//package com.pj.oauth2.custom_scope;
//
//import cn.dev33.satoken.oauth2.data.model.oidc.IdTokenModel;
//import cn.dev33.satoken.oauth2.scope.handler.OidcScopeHandler;

View File

@ -1,4 +1,4 @@
//package com.pj.oauth2.custom;
//package com.pj.oauth2.custom_scope;
//
//import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
//import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
@ -9,17 +9,20 @@
//import java.util.Map;
//
///**
// * 自定义 userinfo scope 处理器
// * @author click33
// * @since 2024/8/20
// */
//@Component
//public class UserinfoScopeHandler implements SaOAuth2ScopeHandlerInterface {
//
// // 指示当前处理器所要处理的 scope
// @Override
// public String getHandlerScope() {
// return "userinfo";
// }
//
// // 当构建的 AccessToken 具有此权限时所需要执行的方法
// @Override
// public void workAccessToken(AccessTokenModel at) {
// System.out.println("--------- userinfo 权限,加工 AccessTokenModel --------- ");
@ -34,8 +37,16 @@
// at.extraData.put("userinfo", map);
// }
//
// // 当构建的 ClientToken 具有此权限时所需要执行的方法
// @Override
// public void workClientToken(ClientTokenModel ct) {
// }
//
// // 当使用 RefreshToken 刷新 AccessToken 是否重新执行 workAccessToken 构建方法
// // 在一些实时性较高的数据中需要指定为 true
// @Override
// public boolean refreshAccessTokenIsWork() {
// return true;
// }
//
//}

View File

@ -96,14 +96,19 @@ http://sa-oauth-server.com:8000/oauth2/userinfo?access_token=${access_token}
在 oauth2-server 新建 `UserinfoScopeHandler.java` 实现 `SaOAuth2ScopeHandlerInterface` 接口:
``` java
/**
* 自定义 userinfo scope 处理器
*/
@Component
public class UserinfoScopeHandler implements SaOAuth2ScopeHandlerInterface {
// 指示当前处理器所要处理的 scope
@Override
public String getHandlerScope() {
return "userinfo";
}
// 当构建的 AccessToken 具有此权限时,所需要执行的方法
@Override
public void workAccessToken(AccessTokenModel at) {
System.out.println("--------- userinfo 权限,加工 AccessTokenModel --------- ");
@ -118,10 +123,18 @@ public class UserinfoScopeHandler implements SaOAuth2ScopeHandlerInterface {
at.extraData.putAll(map);
}
// 当构建的 ClientToken 具有此权限时,所需要执行的方法
@Override
public void workClientToken(ClientTokenModel ct) {
}
// 当使用 RefreshToken 刷新 AccessToken 时,是否重新执行 workAccessToken 构建方法
// 在一些实时性较高的数据中需要指定为 true
@Override
public boolean refreshAccessTokenIsWork() {
return true;
}
}
```

View File

@ -33,6 +33,9 @@ SaOAuth2Util.checkRedirectUri(clientId, url);
// 判断:指定 loginId 是否对一个 Client 授权给了指定 Scope
SaOAuth2Util.isGrantScope(loginId, clientId, scopes);
// 删除:指定 loginId 针对指定 Client 的授权信息
SaOAuth2Util.deleteGrantScope(loginId, clientId);
```
@ -57,8 +60,8 @@ SaOAuth2Util.getAccessToken(accessToken);
// 校验 Access-Token成功返回 AccessTokenModel失败则抛出异常
SaOAuth2Util.checkAccessToken(accessToken);
// 获取 Access-Token,根据索引: clientId、loginId
SaOAuth2Util.getAccessTokenValue(clientId, loginId);
// 获取 Access-Token 列表:此应用下 对 某个用户 签发的所有 Access-token
SaOAuth2Util.getAccessTokenValueList(clientId, loginId);
// 判断:指定 Access-Token 是否具有指定 Scope 列表,返回 true 或 false
SaOAuth2Util.hasAccessTokenScope(accessToken, ...scopes);
@ -72,10 +75,10 @@ SaOAuth2Util.getLoginIdByAccessToken(accessToken);
// 获取 Access-Token 所代表的 clientId
SaOAuth2Util.getClientIdByAccessToken(accessToken);
// 回收 Access-Token
// 回收一个 Access-Token
SaOAuth2Util.revokeAccessToken(accessToken);
// 回收 Access-Token根据索引 clientId、loginId
// 回收全部 Access-Token指定应用下 指定用户 的全部 Access-Token
SaOAuth2Util.revokeAccessTokenByIndex(clientId, loginId);
```
@ -88,8 +91,14 @@ SaOAuth2Util.getRefreshToken(refreshToken);
// 校验 Refresh-Token成功返回 RefreshTokenModel失败则抛出异常
SaOAuth2Util.checkRefreshToken(refreshToken);
// 获取 Refresh-Token根据索引 clientId、loginId
SaOAuth2Util.getRefreshTokenValue(clientId, Object loginId);
// 获取 Refresh-Token 列表:此应用下 对 某个用户 签发的所有 Refresh-Token
SaOAuth2Util.getRefreshTokenValueList(clientId, loginId);
// 回收一个 Refresh-Token
SaOAuth2Util.revokeRefreshToken(refreshToken);
// 回收全部 Refresh-Token指定应用下 指定用户 的全部 Refresh-Token
SaOAuth2Util.revokeRefreshTokenByIndex(clientId, loginId);
// 根据 RefreshToken 刷新出一个 AccessToken
SaOAuth2Util.refreshAccessToken(refreshToken);
@ -105,8 +114,8 @@ SaOAuth2Util.getClientToken(clientToken);
// 校验 Client-Token成功返回 ClientTokenModel失败则抛出异常
SaOAuth2Util.checkClientToken(clientToken);
// 获取 ClientToken根据索引 clientId
SaOAuth2Util.getClientTokenValue(clientId);
// 获取 Client-Token 列表:此应用下 对 某个用户 签发的所有 Client-token
SaOAuth2Util.getClientTokenValueList(clientId);
// 判断:指定 Client-Token 是否具有指定 Scope 列表,返回 true 或 false
SaOAuth2Util.hasClientTokenScope(clientToken, ...scopes);
@ -114,14 +123,11 @@ SaOAuth2Util.hasClientTokenScope(clientToken, ...scopes);
// 校验:指定 Client-Token 是否具有指定 Scope 列表,如果不具备则抛出异常
SaOAuth2Util.checkClientTokenScope(clientToken, ...scopes);
// 回收 ClientToken
// 回收一个 ClientToken
SaOAuth2Util.revokeClientToken(clientToken);
// 回收 ClientToken根据索引 clientId
// 回收全部 Client-Token指定应用下的全部 Client-Token
SaOAuth2Util.revokeClientTokenByIndex(clientId);
// 回收 Lower-ClientToken根据索引 clientId
SaOAuth2Util.revokeLowerClientTokenByIndex(clientId);
```
---

View File

@ -65,20 +65,26 @@ public class SaOAuth2ServerH5Controller {
// 3、构建请求 Model
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, loginId);
// 4、校验重定向域名是否合法
// 4、开发者自定义的授权前置检查
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(ra.loginId, ra.clientId);
// 5、校验重定向域名是否合法
oauth2Template.checkRedirectUri(ra.clientId, ra.redirectUri);
// 5、校验此次申请的Scope该Client是否已经签约
// 6、校验此次申请的Scope该Client是否已经签约
oauth2Template.checkContractScope(ra.clientId, ra.scopes);
// 6、判断如果此次申请的Scope该用户尚未授权则转到授权页面
// 7、判断如果此次申请的Scope该用户尚未授权则转到授权页面
boolean isNeedCarefulConfirm = oauth2Template.isNeedCarefulConfirm(ra.loginId, ra.clientId, ra.scopes);
if(isNeedCarefulConfirm) {
// code=411需要用户手动确认授权
return SaResult.get(411, "need confirm", null);
SaClientModel cm = oauth2Template.checkClientModel(ra.clientId);
if( ! cm.getIsAutoConfirm()) {
// code=411需要用户手动确认授权
return SaResult.get(411, "need confirm", null);
}
}
// 7、判断授权类型重定向到不同地址
// 8、判断授权类型,重定向到不同地址
// 如果是 授权码式开始重定向授权下放code
if(SaOAuth2Consts.ResponseType.code.equals(ra.responseType)) {
CodeModel codeModel = dataGenerate.generateCode(ra);

View File

@ -227,9 +227,9 @@ http://sa-oauth-server.com:8000/oauth2/authorize?response_type=code&client_id=10
2、由于首次访问我们在OAuth-Server端暂未登录会被转发到登录视图
![sa-oauth2-server-login-view](https://oss.dev33.cn/sa-token/doc/oauth2-new/sa-oauth2-server-login-view.png 's-w-sh')
![sa-oauth2-server-login-view](https://oss.dev33.cn/sa-token/doc/oauth2-new/sa-oauth2-server-login-view--v43.png 's-w-sh')
3、点击doLogin进行登录之后刷新页面,会提示我们确认授权
3、输入 `sa/123456` 进行登录之后,会提示我们确认授权
![sa-oauth2-server-scope](https://oss.dev33.cn/sa-token/doc/oauth2-new/sa-oauth2-server-scope.png 's-w-sh')
4、点击同意授权之后我们会被重定向至 redirect_uri 页面并携带了code参数

View File

@ -424,25 +424,31 @@ sa-token.sso-server.clients.sso-client2.secret-key=SSO-C2-kQwIOrYvnXmSDkwEiFngrK
### 4、OAuth2.0相关配置
#### 4.1、OAuth2-Server 相关配置
| 参数名称 | 类型 | 默认值 | 说明 |
| :-------- | :-------- | :-------- | :-------- |
| enableAuthorizationCode | Boolean | true | 是否打开模式:授权码(`Authorization Code` |
| enableImplicit | Boolean | true | 是否打开模式:隐藏式(`Implicit` |
| enablePassword | Boolean | true | 是否打开模式:密码式(`Password` |
| enableClientCredentials | Boolean | true | 是否打开模式:凭证式(`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` 保存的时间(单位:秒) 默认两个小时 |
| lowerClientTokenTimeout | long | 7200 | `Lower-Client-Token` 保存的时间(单位:秒) ,默认为-1代表延续 `Client-Token` 的有效时间 |
| accessTokenTimeout | long | 7200 | 全局默认配置所有应用:`Access-Token` 保存的时间(单位:秒)默认两个小时 |
| refreshTokenTimeout | long | 2592000 | 全局默认配置所有应用:`Refresh-Token` 保存的时间(单位:秒) 默认30 天 |
| clientTokenTimeout | long | 7200 | 全局默认配置所有应用:`Client-Token` 保存的时间(单位:秒) 默认两个小时 |
| maxAccessTokenCount | int | 12 | 全局默认配置所有应用:单个应用单个用户最多同时存在的 Access-Token 数量 |
| maxRefreshTokenCount | int | 12 | 全局默认配置所有应用:单个应用单个用户最多同时存在的 Refresh-Token 数量 |
| maxClientTokenCount | int | 12 | 全局默认配置所有应用:单个应用最多同时存在的 Client-Token 数量 |
| isNewRefresh | Boolean | false | 全局默认配置所有应用:是否在每次 `Refresh-Token` 刷新 `Access-Token` 时,产生一个新的 `Refresh-Token` |
| openidDigestPrefix | String | openid_default_digest_prefix | 默认 openid 生成算法中使用的摘要前缀 |
| unionidDigestPrefix | String | unionid_default_digest_prefix | 默认 unionid 生成算法中使用的摘要前缀 |
| higherScope | String | | 指定高级权限,多个用逗号隔开 |
| lowerScope | String | | 指定低级权限,多个用逗号隔开 |
| mode4ReturnAccessToken | Boolean | false | 模式4是否返回 AccessToken 字段用于兼容OAuth2标准协议 |
| hideStatusField | Boolean | false | 是否在返回值中隐藏默认的状态字段 (code、msg、data) |
| oidc | SaOAuth2OidcConfig | new SaOAuth2OidcConfig() | OIDC 相关配置 |
| oidc | SaOAuth2OidcConfig | new SaOAuth2OidcConfig() | OIDC 相关配置 |
| clients | Map<String, SaClientModel> | 配置 SaClientModel 列表信息 |
配置示例:
<!---------------------------- tabs:start ---------------------------->
@ -471,7 +477,7 @@ sa-token.oauth2-server.enable-client-credentials=true
<!---------------------------- tabs:end ---------------------------->
##### OIDC 相关配置
#### 4.2、OIDC 相关配置
| 参数名称 | 类型 | 默认值 | 说明 |
| :-------- | :-------- | :-------- | :-------- |
| iss | String | | iss 值,如不配置则自动计算 |
@ -496,19 +502,25 @@ sa-token.oauth2-server.oidc.idTokenTimeout=600
##### SaClientModel属性定义
#### 4.3、SaClientModel属性定义
| 参数名称 | 类型 | 默认值 | 说明 |
| :-------- | :-------- | :-------- | :-------- |
| clientId | String | null | 应用id应该全局唯一 |
| clientSecret | String | null | 应用秘钥 |
| contractScopes | List<String> | null | 应用签约的所有权限 |
| allowRedirectUris | List<String> | null | 应用允许授权的所有URL可以使用 `*` 号通配符) |
| allowGrantTypes | List<String> | new ArrayList<>() | 应用允许的所有 `grant_type` |
| isNewRefresh | Boolean | 取全局配置 | 单独配置此Client是否在每次 `Refresh-Token` 刷新 `Access-Token` 时,产生一个新的 Refresh-Token [ 默认取全局配置 ] |
| accessTokenTimeout | long | 取全局配置 | 单独配置此Client`Access-Token` 保存的时间(单位:秒) [默认取全局配置] |
| refreshTokenTimeout | long | 取全局配置 | 单独配置此Client`Refresh-Token` 保存的时间(单位:秒) [默认取全局配置] |
| clientTokenTimeout | long | 取全局配置 | 单独配置此Client`Client-Token` 保存的时间(单位:秒) [默认取全局配置] |
|lowerClientTokenTimeout | long | 取全局配置 | 单独配置此Client`Lower-Client-Token` 保存的时间(单位:秒) [默认取全局配置] |
| contractScopes | List<String> | [] | 应用签约的所有权限 |
| allowRedirectUris | List<String> | [] | 应用允许授权的所有URL可以使用 `*` 号通配符) |
| allowGrantTypes | List<String> | [] | 应用允许的所有 `grant_type` |
| subjectId | String | null | 应用主体id |
| accessTokenTimeout | long | 取全局配置 (7200) | 此应用`Access-Token` 保存的时间(单位:秒) [默认取全局配置] |
| refreshTokenTimeout | long | 取全局配置 (2592000)| 此应用`Refresh-Token` 保存的时间(单位:秒) [默认取全局配置] |
| clientTokenTimeout | Boolean | 取全局配置 (7200)| 此应用`Client-Token` 保存的时间(单位:秒) [默认取全局配置] |
| maxAccessTokenCount | long | 取全局配置 (12)| 此应用单个用户最多同时存在的 Access-Token 数量 |
| maxRefreshTokenCount | long | 取全局配置 (12)| 此应用单个用户最多同时存在的 Refresh-Token 数量 |
| maxClientTokenCount | long | 取全局配置 (12)| 此应用最多同时存在的 Client-Token 数量 |
| isNewRefresh | Boolean | 取全局配置 | 单独配置此 Client是否在每次 `Refresh-Token` 刷新 `Access-Token` 时,产生一个新的 Refresh-Token [ 默认取全局配置 ] |
| isAutoConfirm | Boolean | false | 是否允许此应用自动确认授权 <span style="color: red;">(高危配置,禁止向不被信任的第三方开启此选项)</span> |

View File

@ -45,12 +45,12 @@ public class SaClientModel implements Serializable {
/**
* 应用签约的所有权限
*/
public List<String> contractScopes;
public List<String> contractScopes = new ArrayList<>();
/**
* 应用允许授权的所有 redirect_uri
*/
public List<String> allowRedirectUris;
public List<String> allowRedirectUris = new ArrayList<>();
/**
* 应用允许的所有 grant_type
@ -62,24 +62,15 @@ public class SaClientModel implements Serializable {
*/
public String subjectId;
/** 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
public Boolean isNewRefresh;
/** 单独配置此ClientAccess-Token 保存的时间(单位秒) [默认取全局配置] */
/** 此应用 Access-Token 保存的时间(单位秒) [默认取全局配置] */
public long accessTokenTimeout;
/** 单独配置此ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置] */
/** 此应用 Refresh-Token 保存的时间(单位秒) [默认取全局配置] */
public long refreshTokenTimeout;
/** 单独配置此ClientClient-Token 保存的时间(单位秒) [默认取全局配置] */
/** 此应用 Client-Token 保存的时间(单位秒) [默认取全局配置] */
public long clientTokenTimeout;
/** 单独配置此ClientLower-Client-Token 保存的时间(单位:秒) [默认取全局配置] */
public long lowerClientTokenTimeout;
/** 是否允许此应用自动确认授权(高危配置,禁止向不被信任的第三方开启此选项) */
public Boolean isAutoConfirm = false;
/** 此应用单个用户最多同时存在的 Access-Token 数量 */
public int maxAccessTokenCount;
@ -89,6 +80,12 @@ public class SaClientModel implements Serializable {
/** 此应用最多同时存在的 Client-Token 数量 */
public int maxClientTokenCount;
/** 此应用 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token [默认取全局配置] */
public Boolean isNewRefresh;
/** 是否允许此应用自动确认授权(高危配置,禁止向不被信任的第三方开启此选项) */
public Boolean isAutoConfirm = false;
public SaClientModel() {
SaOAuth2Strategy.instance.setSaClientModelDefaultFields.run(this);
@ -244,14 +241,14 @@ public class SaClientModel implements Serializable {
}
/**
* @return Client是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
* @return 应用 是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
*/
public Boolean getIsNewRefresh() {
return isNewRefresh;
}
/**
* @param isNewRefresh 单独配置此Client是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
* @param isNewRefresh 此应用 是否在每次 Refresh-Token 刷新 Access-Token 产生一个新的 Refresh-Token [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setIsNewRefresh(Boolean isNewRefresh) {
@ -260,14 +257,14 @@ public class SaClientModel implements Serializable {
}
/**
* @return ClientAccess-Token 保存的时间(单位秒) [默认取全局配置]
* @return 应用 Access-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getAccessTokenTimeout() {
return accessTokenTimeout;
}
/**
* @param accessTokenTimeout 单独配置此ClientAccess-Token 保存的时间(单位秒) [默认取全局配置]
* @param accessTokenTimeout 此应用 Access-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setAccessTokenTimeout(long accessTokenTimeout) {
@ -276,14 +273,14 @@ public class SaClientModel implements Serializable {
}
/**
* @return ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置]
* @return 应用 Refresh-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getRefreshTokenTimeout() {
return refreshTokenTimeout;
}
/**
* @param refreshTokenTimeout 单独配置此ClientRefresh-Token 保存的时间(单位秒) [默认取全局配置]
* @param refreshTokenTimeout 此应用 Refresh-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setRefreshTokenTimeout(long refreshTokenTimeout) {
@ -292,36 +289,20 @@ public class SaClientModel implements Serializable {
}
/**
* @return ClientClient-Token 保存的时间(单位秒) [默认取全局配置]
* @return 应用 Client-Token 保存的时间(单位秒) [默认取全局配置]
*/
public long getClientTokenTimeout() {
return clientTokenTimeout;
}
/**
* @param clientTokenTimeout 单独配置此ClientClient-Token 保存的时间(单位秒) [默认取全局配置]
* @param clientTokenTimeout 此应用 Client-Token 保存的时间(单位秒) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setClientTokenTimeout(long clientTokenTimeout) {
this.clientTokenTimeout = clientTokenTimeout;
return this;
}
/**
* @return 此ClientLower-Client-Token 保存的时间(单位) [默认取全局配置]
*/
public long getLowerClientTokenTimeout() {
return lowerClientTokenTimeout;
}
/**
* @param lowerClientTokenTimeout 单独配置此ClientLower-Client-Token 保存的时间(单位) [默认取全局配置]
* @return 对象自身
*/
public SaClientModel setLowerClientTokenTimeout(long lowerClientTokenTimeout) {
this.lowerClientTokenTimeout = lowerClientTokenTimeout;
return this;
}
/**
* 获取 是否允许此应用自动确认授权高危配置禁止向不被信任的第三方开启此选项
@ -410,7 +391,6 @@ public class SaClientModel implements Serializable {
", accessTokenTimeout=" + accessTokenTimeout +
", refreshTokenTimeout=" + refreshTokenTimeout +
", clientTokenTimeout=" + clientTokenTimeout +
", lowerClientTokenTimeout=" + lowerClientTokenTimeout +
", isAutoConfirm=" + isAutoConfirm +
", maxAccessTokenCount=" + maxAccessTokenCount +
", refreshTokenTimeout=" + refreshTokenTimeout +