重构代码:OAuth2 授权模式开放由全局配置和Client单独配置共同设定

This commit is contained in:
click33 2021-12-23 04:19:34 +08:00
parent ebec86f0de
commit e2463b7e03
6 changed files with 139 additions and 57 deletions

View File

@ -21,7 +21,8 @@ public class SaOAuth2TemplateImpl extends SaOAuth2Template {
.setClientId("10001")
.setClientSecret("aaaa-bbbb-cccc-dddd-eeee")
.setAllowUrl("*")
.setContractScope("userinfo");
.setContractScope("userinfo")
.setIsAutoMode(true);
}
return null;
}

View File

@ -16,19 +16,15 @@ public class SaOAuth2Config implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/** 是否打开模式授权码Authorization Code */
@Deprecated
public Boolean isCode = true;
/** 是否打开模式隐藏式Implicit */
@Deprecated
public Boolean isImplicit = false;
/** 是否打开模式密码式Password */
@Deprecated
public Boolean isPassword = false;
/** 是否打开模式凭证式Client Credentials */
@Deprecated
public Boolean isClient = false;
/** 是否在每次 Refresh-Token 刷新 Access-Token 时,产生一个新的 Refresh-Token */

View File

@ -14,6 +14,7 @@ import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.oauth2.model.SaClientModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
@ -35,16 +36,17 @@ public class SaOAuth2Handle {
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
//读取client_id,此参数在所有模式中必填
String clientId = req.getParamNotNull(Param.client_id);
// ------------------ 路由分发 ------------------
// 模式一Code授权码
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code) && (SaOAuth2Util.supportType(clientId,GrantType.authorization_code) || cfg.isCode)) {
return authorize(req, res, cfg);
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code)) {
SaClientModel cm = currClientModel();
if(cfg.isCode && (cm.isCode || cm.isAutoMode)) {
return authorize(req, res, cfg);
}
throw new SaOAuth2Exception("暂未开放的授权模式");
}
// Code授权码 获取 Access-Token
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.authorization_code)) {
return token(req, res, cfg);
@ -71,18 +73,31 @@ public class SaOAuth2Handle {
}
// 模式二隐藏式
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token) && (SaOAuth2Util.supportType(clientId,GrantType.implicit) || cfg.isImplicit)) {
return authorize(req, res, cfg);
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token)) {
SaClientModel cm = currClientModel();
if(cfg.isImplicit && (cm.isImplicit || cm.isAutoMode)) {
return authorize(req, res, cfg);
}
throw new SaOAuth2Exception("暂未开放的授权模式");
}
// 模式三密码式
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password) && (SaOAuth2Util.supportType(clientId,GrantType.password) || cfg.isPassword)) {
return password(req, res, cfg);
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password)) {
SaClientModel cm = currClientModel();
if(cfg.isPassword && (cm.isPassword || cm.isAutoMode)) {
return password(req, res, cfg);
}
throw new SaOAuth2Exception("暂未开放的授权模式");
}
// 模式四凭证式
if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials) && (SaOAuth2Util.supportType(clientId,GrantType.client_credentials) || cfg.isClient)) {
return clientToken(req, res, cfg);
if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials)) {
SaClientModel cm = currClientModel();
if(cfg.isClient && (cm.isClient || cm.isAutoMode)) {
return clientToken(req, res, cfg);
}
throw new SaOAuth2Exception("暂未开放的授权模式");
}
// 默认返回
@ -97,7 +112,7 @@ public class SaOAuth2Handle {
* @return 处理结果
*/
public static Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1如果尚未登录, 则先去登录
if(StpUtil.isLogin() == false) {
return cfg.notLoginView.get();
@ -125,6 +140,7 @@ public class SaOAuth2Handle {
String redirectUri = SaOAuth2Util.buildRedirectUri(ra.redirectUri, codeModel.code, ra.state);
return res.redirect(redirectUri);
}
// 如果是 隐藏式开始重定向授权下放 token
if(ResponseType.token.equals(ra.responseType)) {
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, false);
@ -296,4 +312,13 @@ public class SaOAuth2Handle {
return SaResult.data(ct.toLineMap());
}
/**
* 根据当前请求提交的 client_id 参数获取 SaClientModel 对象
* @return /
*/
public static SaClientModel currClientModel() {
String clientId = SaHolder.getRequest().getParam(Param.client_id);
return SaOAuth2Util.checkClientModel(clientId);
}
}

View File

@ -1,17 +1,21 @@
package cn.dev33.satoken.oauth2.logic;
import java.util.List;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.model.*;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.oauth2.model.SaClientModel;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.Arrays;
import java.util.List;
/**
* Sa-Token-OAuth2 模块 代码实现
* @author kong
@ -918,12 +922,4 @@ public class SaOAuth2Template {
return SaManager.getConfig().getTokenName() + ":oauth2:grant-scope:" + clientId + ":" + loginId;
}
/**
* 检查是否支持的type类型
*/
public Boolean supportType(String clientId,String type){
SaClientModel saClientModel = checkClientModel(clientId);
return Arrays.asList(saClientModel.getAllowType().split(",")).contains(type);
}
}

View File

@ -293,16 +293,4 @@ public class SaOAuth2Util {
return saOAuth2Template.getGrantScope(clientId, loginId);
}
/**
* 获取检查是否支持的授权类型
* @param clientId 应用id
* @param type 授权类型
* @return 是否
*/
public static Boolean supportType(String clientId, String type) {
return saOAuth2Template.supportType(clientId, type);
}
}

View File

@ -30,22 +30,31 @@ public class SaClientModel implements Serializable {
* 应用允许授权的所有URL, 多个用逗号隔开
*/
public String allowUrl;
/** 此 Client 是否打开模式授权码Authorization Code */
public Boolean isCode = false;
/**
* 应用允许授权的所有URL, 多个用逗号隔开
*/
public String allowType;
/** 此 Client 是否打开模式隐藏式Implicit */
public Boolean isImplicit = false;
/** 此 Client 是否打开模式密码式Password */
public Boolean isPassword = false;
/** 此 Client 是否打开模式凭证式Client Credentials */
public Boolean isClient = false;
/** 是否自动判断开放的授权模式此值为true时单独设置isCode、isImplicit、isPassword、isClient不再有效而是跟随全局设置 */
public Boolean isAutoMode = false;
public SaClientModel() {
}
public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl,String allowType) {
public SaClientModel(String clientId, String clientSecret, String contractScope, String allowUrl) {
super();
this.clientId = clientId;
this.clientSecret = clientSecret;
this.contractScope = contractScope;
this.allowUrl = allowUrl;
this.allowType = allowType;
}
/**
@ -113,25 +122,92 @@ public class SaClientModel implements Serializable {
}
/**
* @return 应用允许的授权模式, 多个用逗号隔开
* @return Client 是否打开模式授权码Authorization Code
*/
public String getAllowType() {
return allowType;
public Boolean getIsCode() {
return isCode;
}
/**
* @param allowType 应用允许的授权模式, 多个用逗号隔开
* @return 对象自身
* @param isCode Client 是否打开模式授权码Authorization Code
* @return 对象自身
*/
public SaClientModel setAllowType(String allowType) {
this.allowType = allowType;
public SaClientModel setIsCode(Boolean isCode) {
this.isCode = isCode;
return this;
}
/**
* @return Client 是否打开模式隐藏式Implicit
*/
public Boolean getIsImplicit() {
return isImplicit;
}
/**
* @param isImplicit Client 是否打开模式隐藏式Implicit
* @return 对象自身
*/
public SaClientModel setIsImplicit(Boolean isImplicit) {
this.isImplicit = isImplicit;
return this;
}
/**
* @return Client 是否打开模式密码式Password
*/
public Boolean getIsPassword() {
return isPassword;
}
/**
* @param isPassword Client 是否打开模式密码式Password
* @return 对象自身
*/
public SaClientModel setIsPassword(Boolean isPassword) {
this.isPassword = isPassword;
return this;
}
/**
* @return Client 是否打开模式凭证式Client Credentials
* @return 对象自身
*/
public Boolean getIsClient() {
return isClient;
}
/**
* @param isClient Client 是否打开模式凭证式Client Credentials
* @return 对象自身
*/
public SaClientModel setIsClient(Boolean isClient) {
this.isClient = isClient;
return this;
}
/**
* @return 是否自动判断开放的授权模式
*/
public Boolean getIsAutoMode() {
return isAutoMode;
}
/**
* @param isAutoMode 是否自动判断开放的授权模式
* @return 对象自身
*/
public SaClientModel setIsAutoMode(Boolean isAutoMode) {
this.isAutoMode = isAutoMode;
return this;
}
//
@Override
public String toString() {
return "SaClientModel [clientId=" + clientId + ", clientSecret=" + clientSecret + ", contractScope="
+ contractScope + ", allowUrl=" + allowUrl + "]";
+ contractScope + ", allowUrl=" + allowUrl + ", isCode=" + isCode + ", isImplicit=" + isImplicit
+ ", isPassword=" + isPassword + ", isClient=" + isClient + ", isAutoMode=" + isAutoMode + "]";
}
}