!78 修改Oauth2 凭证式缺少校验scope 问题

Merge pull request !78 from 茉莉/dev
This commit is contained in:
省长 2021-10-27 03:10:00 +00:00 committed by Gitee
commit eb1ec5676c

View File

@ -18,7 +18,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* Sa-Token-OAuth2 请求处理类封装
* Sa-Token-OAuth2 请求处理类封装
* @author kong
*
*/
@ -26,195 +26,195 @@ public class SaOAuth2Handle {
/**
* 处理Server端请求 路由分发
* @return 处理结果
* @return 处理结果
*/
public static Object serverRequest() {
// 获取变量
// 获取变量
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaOAuth2Config cfg = SaOAuth2Manager.getConfig();
// ------------------ 路由分发 ------------------
// ------------------ 路由分发 ------------------
// 模式一Code授权码
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.code) && cfg.isCode) {
return authorize(req, res, cfg);
}
// Code授权码 获取 Access-Token
// Code授权码 获取 Access-Token
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.authorization_code)) {
return token(req, res, cfg);
}
// Refresh-Token 刷新 Access-Token
// Refresh-Token 刷新 Access-Token
if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) {
return refreshToken(req);
}
// 回收 Access-Token
// 回收 Access-Token
if(req.isPath(Api.revoke)) {
return revokeToken(req);
}
// doLogin 登录接口
// doLogin 登录接口
if(req.isPath(Api.doLogin)) {
return doLogin(req, res, cfg);
}
// doConfirm 确认授权接口
// doConfirm 确认授权接口
if(req.isPath(Api.doConfirm)) {
return doConfirm(req);
}
// 模式二隐藏式
// 模式二隐藏式
if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token) && cfg.isImplicit) {
return authorize(req, res, cfg);
}
// 模式三密码式
// 模式三密码式
if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password) && cfg.isPassword) {
return password(req, res, cfg);
}
// 模式四凭证式
// 模式四凭证式
if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials) && cfg.isClient) {
return clientToken(req, res, cfg);
}
// 默认返回
// 默认返回
return SaOAuth2Consts.NOT_HANDLE;
}
/**
* 模式一Code授权码 / 模式二隐藏式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1如果尚未登录, 则先去登录
/**
* 模式一Code授权码 / 模式二隐藏式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1如果尚未登录, 则先去登录
if(StpUtil.isLogin() == false) {
return cfg.notLoginView.get();
}
// 2构建请求Model
// 2构建请求Model
RequestAuthModel ra = SaOAuth2Util.generateRequestAuth(req, StpUtil.getLoginId());
// 3校验重定向域名是否合法
// 3校验重定向域名是否合法
SaOAuth2Util.checkRightUrl(ra.clientId, ra.redirectUri);
// 4校验此次申请的Scope该Client是否已经签约
// 4校验此次申请的Scope该Client是否已经签约
SaOAuth2Util.checkContract(ra.clientId, ra.scope);
// 5判断如果此次申请的Scope该用户尚未授权则转到授权页面
// 5判断如果此次申请的Scope该用户尚未授权则转到授权页面
boolean isGrant = SaOAuth2Util.isGrant(ra.loginId, ra.clientId, ra.scope);
if(isGrant == false) {
return cfg.confirmView.apply(ra.clientId, ra.scope);
}
// 6判断授权类型
// 如果是 授权码式开始重定向授权下放code
// 6判断授权类型
// 如果是 授权码式开始重定向授权下放code
if(ResponseType.code.equals(ra.responseType)) {
CodeModel codeModel = SaOAuth2Util.generateCode(ra);
CodeModel codeModel = SaOAuth2Util.generateCode(ra);
String redirectUri = SaOAuth2Util.buildRedirectUri(ra.redirectUri, codeModel.code, ra.state);
return res.redirect(redirectUri);
return res.redirect(redirectUri);
}
// 如果是 隐藏式开始重定向授权下放 token
// 如果是 隐藏式开始重定向授权下放 token
if(ResponseType.token.equals(ra.responseType)) {
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, false);
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, false);
String redirectUri = SaOAuth2Util.buildImplicitRedirectUri(ra.redirectUri, at.accessToken, ra.state);
return res.redirect(redirectUri);
return res.redirect(redirectUri);
}
// 默认返回
throw new SaOAuth2Exception("无效response_type: " + ra.responseType);
// 默认返回
throw new SaOAuth2Exception("无效response_type: " + ra.responseType);
}
/**
* Code授权码 获取 Access-Token
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* Code授权码 获取 Access-Token
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 获取参数
String code = req.getParamNotNull(Param.code);
String clientId = req.getParamNotNull(Param.client_id);
// 获取参数
String code = req.getParamNotNull(Param.code);
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String redirectUri = req.getParam(Param.redirect_uri);
String redirectUri = req.getParam(Param.redirect_uri);
// 校验参数
SaOAuth2Util.checkGainTokenParam(code, clientId, clientSecret, redirectUri);
// 构建 Access-Token
// 构建 Access-Token
AccessTokenModel token = SaOAuth2Util.generateAccessToken(code);
// 返回
return SaResult.data(token.toLineMap());
// 返回
return SaResult.data(token.toLineMap());
}
/**
* Refresh-Token 刷新 Access-Token
* @param req 请求对象
* @return 处理结果
* Refresh-Token 刷新 Access-Token
* @param req 请求对象
* @return 处理结果
*/
public static Object refreshToken(SaRequest req) {
// 获取参数
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String refreshToken = req.getParamNotNull(Param.refresh_token);
// 校验参数
// 校验参数
SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
// 获取新Token返回
// 获取新Token返回
Object data = SaOAuth2Util.refreshAccessToken(refreshToken).toLineMap();
return SaResult.data(data);
return SaResult.data(data);
}
/**
* 回收 Access-Token
* @param req 请求对象
* @return 处理结果
* 回收 Access-Token
* @param req 请求对象
* @return 处理结果
*/
public static Object revokeToken(SaRequest req) {
// 获取参数
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String accessToken = req.getParamNotNull(Param.access_token);
// 如果 Access-Token 不存在直接返回
if(SaOAuth2Util.getAccessToken(accessToken) == null) {
return SaResult.ok("access_token不存在" + accessToken);
}
// 校验参数
// 校验参数
SaOAuth2Util.checkAccessTokenParam(clientId, clientSecret, accessToken);
// 获取新Token返回
// 获取新Token返回
SaOAuth2Util.revokeAccessToken(accessToken);
return SaResult.ok();
return SaResult.ok();
}
/**
* doLogin 登录接口
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* doLogin 登录接口
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object doLogin(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
return cfg.doLoginHandle.apply(req.getParamNotNull(Param.name), req.getParamNotNull("pwd"));
}
/**
* doConfirm 确认授权接口
* @param req 请求对象
* @return 处理结果
* doConfirm 确认授权接口
* @param req 请求对象
* @return 处理结果
*/
public static Object doConfirm(SaRequest req) {
String clientId = req.getParamNotNull(Param.client_id);
@ -223,68 +223,71 @@ public class SaOAuth2Handle {
SaOAuth2Util.saveGrantScope(clientId, loginId, scope);
return SaResult.ok();
}
/**
* 模式三密码式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* 模式三密码式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object password(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 1获取请求参数
// 1获取请求参数
String username = req.getParamNotNull(Param.username);
String password = req.getParamNotNull(Param.password);
String clientId = req.getParamNotNull(Param.client_id);
// 2校验client_id
SaOAuth2Util.checkClientModel(clientId);
// 3防止因前端误传token造成逻辑干扰
// 3防止因前端误传token造成逻辑干扰
SaHolder.getStorage().set(StpUtil.stpLogic.splicingKeyJustCreatedSave(), "no-token");
// 4调用API 开始登录如果没能成功登录则直接退出
Object retObj = cfg.doLoginHandle.apply(username, password);
Object retObj = cfg.doLoginHandle.apply(username, password);
if(StpUtil.isLogin() == false) {
return retObj;
}
// 5构建 ra对象
// 5构建 ra对象
RequestAuthModel ra = new RequestAuthModel();
ra.clientId = clientId;
ra.loginId = StpUtil.getLoginId();
ra.scope = req.getParam(Param.scope, "");
// 6生成 Access-Token
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, true);
// 7返回 Access-Token
ra.loginId = StpUtil.getLoginId();
ra.scope = req.getParam(Param.scope, "");
// 6生成 Access-Token
AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, true);
// 7返回 Access-Token
return SaResult.data(at.toLineMap());
}
/**
* 模式四凭证式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* 模式四凭证式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object clientToken(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 获取参数
// 获取参数
String clientId = req.getParamNotNull(Param.client_id);
String clientSecret = req.getParamNotNull(Param.client_secret);
String scope = req.getParam(Param.scope);
//校验 ClientScope
SaOAuth2Util.checkContract(clientId, scope);
// 校验 ClientSecret
SaOAuth2Util.checkClientSecret(clientId, clientSecret);
// 返回 Client-Token
ClientTokenModel ct = SaOAuth2Util.generateClientToken(clientId, scope);
// 返回 Client-Token
return SaResult.data(ct.toLineMap());
return SaResult.data(ct.toLineMap());
}
}