From eeed140424d42890f50dea449c33970c8767c3c5 Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Mon, 12 Aug 2024 07:05:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20sa-token-oauth2=EF=BC=9A?= =?UTF-8?q?=E6=8F=90=E5=8F=96=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=BD=BD=E5=99=A8?= =?UTF-8?q?=20Bean=EF=BC=8C=E6=8F=90=E4=BE=9B=E6=9B=B4=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E7=9A=84=E8=87=AA=E5=AE=9A=E4=B9=89=E6=95=B0=E6=8D=AE=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=96=B9=E6=A1=88=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sa-token-demo-oauth2-server/pom.xml | 4 +- ...eImpl.java => SaOAuth2DataLoaderImpl.java} | 16 +- .../pj/oauth2/SaOAuth2ServerController.java | 21 +- .../dev33/satoken/oauth2/SaOAuth2Manager.java | 20 + .../{logic => consts}/SaOAuth2Consts.java | 4 +- .../oauth2/dataloader/SaOAuth2DataLoader.java | 51 ++ .../SaOAuth2DataLoaderDefaultImpl.java | 28 + .../SaOAuth2ServerProcessor.java} | 708 +++++++++--------- .../{logic => template}/SaOAuth2Template.java | 23 +- .../{logic => template}/SaOAuth2Util.java | 74 +- .../solon/oauth2/SaOAuth2AutoConfigure.java | 4 +- .../spring/oauth2/SaOAuth2BeanInject.java | 30 +- .../spring/oauth2/SaOAuth2BeanRegister.java | 4 +- .../configure/inject/MySaOAuth2Template.java | 2 +- 14 files changed, 547 insertions(+), 442 deletions(-) rename sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/{SaOAuth2TemplateImpl.java => SaOAuth2DataLoaderImpl.java} (76%) rename sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/{logic => consts}/SaOAuth2Consts.java (97%) create mode 100644 sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoader.java create mode 100644 sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoaderDefaultImpl.java rename sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/{logic/SaOAuth2Handle.java => processor/SaOAuth2ServerProcessor.java} (75%) rename sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/{logic => template}/SaOAuth2Template.java (98%) rename sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/{logic => template}/SaOAuth2Util.java (72%) diff --git a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/pom.xml b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/pom.xml index 0363705c..045c07a6 100644 --- a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/pom.xml +++ b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/pom.xml @@ -60,11 +60,11 @@ - + diff --git a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2TemplateImpl.java b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2DataLoaderImpl.java similarity index 76% rename from sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2TemplateImpl.java rename to sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2DataLoaderImpl.java index 758b4090..78080fbd 100644 --- a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2TemplateImpl.java +++ b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2DataLoaderImpl.java @@ -1,18 +1,18 @@ package com.pj.oauth2; +import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoader; +import cn.dev33.satoken.oauth2.model.SaClientModel; import org.springframework.stereotype.Component; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Template; -import cn.dev33.satoken.oauth2.model.SaClientModel; - /** - * Sa-Token OAuth2.0 整合实现 + * Sa-Token OAuth2:自定义数据加载器 + * * @author click33 */ @Component -public class SaOAuth2TemplateImpl extends SaOAuth2Template { +public class SaOAuth2DataLoaderImpl implements SaOAuth2DataLoader { - // 根据 id 获取 Client 信息 + // 根据 client_id 获取 Client 信息 @Override public SaClientModel getClientModel(String clientId) { // 此为模拟数据,真实环境需要从数据库查询 @@ -33,7 +33,5 @@ public class SaOAuth2TemplateImpl extends SaOAuth2Template { // 此为模拟数据,真实环境需要从数据库查询 return "gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__"; } - - // -------------- 其它需要重写的函数 - + } diff --git a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2ServerController.java b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2ServerController.java index 7f49f746..16771edd 100644 --- a/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2ServerController.java +++ b/sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-server/src/main/java/com/pj/oauth2/SaOAuth2ServerController.java @@ -1,21 +1,20 @@ package com.pj.oauth2; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.oauth2.config.SaOAuth2Config; +import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor; +import cn.dev33.satoken.oauth2.template.SaOAuth2Util; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; -import cn.dev33.satoken.context.SaHolder; -import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Handle; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Util; -import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; /** * Sa-OAuth2 Server端 控制器 @@ -29,7 +28,7 @@ public class SaOAuth2ServerController { @RequestMapping("/oauth2/*") public Object request() { System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl()); - return SaOAuth2Handle.serverRequest(); + return SaOAuth2ServerProcessor.instance.dister(); } // Sa-OAuth2 定制化配置 diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/SaOAuth2Manager.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/SaOAuth2Manager.java index 4796a686..05d206ff 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/SaOAuth2Manager.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/SaOAuth2Manager.java @@ -16,6 +16,8 @@ package cn.dev33.satoken.oauth2; import cn.dev33.satoken.oauth2.config.SaOAuth2Config; +import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoader; +import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoaderDefaultImpl; /** * Sa-Token-OAuth2 模块 总控类 @@ -44,4 +46,22 @@ public class SaOAuth2Manager { SaOAuth2Manager.config = config; } + /** + * OAuth2 数据加载器 Bean + */ + private static volatile SaOAuth2DataLoader dataLoader; + public static SaOAuth2DataLoader getDataLoader() { + if (dataLoader == null) { + synchronized (SaOAuth2Manager.class) { + if (dataLoader == null) { + setDataLoader(new SaOAuth2DataLoaderDefaultImpl()); + } + } + } + return dataLoader; + } + public static void setDataLoader(SaOAuth2DataLoader dataLoader) { + SaOAuth2Manager.dataLoader = dataLoader; + } + } diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/consts/SaOAuth2Consts.java similarity index 97% rename from sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java rename to sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/consts/SaOAuth2Consts.java index e1ee9bb7..22a189bc 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Consts.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/consts/SaOAuth2Consts.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.dev33.satoken.oauth2.logic; +package cn.dev33.satoken.oauth2.consts; /** - * Sa-Token-OAuth2 所有常量 + * Sa-Token OAuth2 所有常量 * * @author click33 * @since 1.23.0 diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoader.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoader.java new file mode 100644 index 00000000..5b94679c --- /dev/null +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoader.java @@ -0,0 +1,51 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.oauth2.dataloader; + +import cn.dev33.satoken.oauth2.model.SaClientModel; + +/** + * Sa-Token OAuth2 数据加载器 + * + * @author click33 + * @since 1.39.0 + */ +public interface SaOAuth2DataLoader { + + /** + * 根据 id 获取 Client 信息 + * + * @param clientId 应用id + * @return ClientModel + */ + default SaClientModel getClientModel(String clientId) { + return null; + } + + /** + * 根据ClientId 和 LoginId 获取openid + * + * @param clientId 应用id + * @param loginId 账号id + * @return 此账号在此Client下的openid + */ + default String getOpenid(String clientId, Object loginId) { + return null; + } + + + +} diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoaderDefaultImpl.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoaderDefaultImpl.java new file mode 100644 index 00000000..deedbf9b --- /dev/null +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/dataloader/SaOAuth2DataLoaderDefaultImpl.java @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.oauth2.dataloader; + +/** + * Sa-Token OAuth2 数据加载器 默认实现类 + * + * @author click33 + * @since 1.39.0 + */ +public class SaOAuth2DataLoaderDefaultImpl implements SaOAuth2DataLoader{ + + // be empty of + +} diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java similarity index 75% rename from sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java rename to sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java index 559a38b9..1447e7be 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Handle.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java @@ -1,348 +1,360 @@ -/* - * Copyright 2020-2099 sa-token.cc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package cn.dev33.satoken.oauth2.logic; - -import cn.dev33.satoken.context.SaHolder; -import cn.dev33.satoken.context.model.SaRequest; -import cn.dev33.satoken.context.model.SaResponse; -import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil; -import cn.dev33.satoken.oauth2.SaOAuth2Manager; -import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; -import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Api; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.GrantType; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.ResponseType; -import cn.dev33.satoken.oauth2.model.*; -import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaFoxUtil; -import cn.dev33.satoken.util.SaResult; - -/** - * Sa-Token-OAuth2 请求处理类封装 - * - * @author click33 - * @since 1.23.0 - */ -public class SaOAuth2Handle { - - /** - * 处理Server端请求, 路由分发 - * @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)) { - SaClientModel cm = currClientModel(); - if(cfg.getIsCode() && (cm.isCode || cm.isAutoMode)) { - return authorize(req, res, cfg); - } - throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30131); - } - - // 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 - if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) { - return refreshToken(req); - } - - // 回收 Access-Token - if(req.isPath(Api.revoke)) { - return revokeToken(req); - } - - // doLogin 登录接口 - if(req.isPath(Api.doLogin)) { - return doLogin(req, res, cfg); - } - - // doConfirm 确认授权接口 - if(req.isPath(Api.doConfirm)) { - return doConfirm(req); - } - - // 模式二:隐藏式 - if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token)) { - SaClientModel cm = currClientModel(); - if(cfg.getIsImplicit() && (cm.isImplicit || cm.isAutoMode)) { - return authorize(req, res, cfg); - } - throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30132); - } - - // 模式三:密码式 - if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password)) { - SaClientModel cm = currClientModel(); - if(cfg.getIsPassword() && (cm.isPassword || cm.isAutoMode)) { - return password(req, res, cfg); - } - throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30133); - } - - // 模式四:凭证式 - if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials)) { - SaClientModel cm = currClientModel(); - if(cfg.getIsClient() && (cm.isClient || cm.isAutoMode)) { - return clientToken(req, res, cfg); - } - throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30134); - } - - // 默认返回 - return SaOAuth2Consts.NOT_HANDLE; - } - - /** - * 模式一:Code授权码 / 模式二:隐藏式 - * @param req 请求对象 - * @param res 响应对象 - * @param cfg 配置对象 - * @return 处理结果 - */ - public static Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - - // 1、如果尚未登录, 则先去登录 - if( ! StpUtil.isLogin()) { - return cfg.getNotLoginView().get(); - } - - // 2、构建请求Model - RequestAuthModel ra = SaOAuth2Util.generateRequestAuth(req, StpUtil.getLoginId()); - - // 3、校验:重定向域名是否合法 - SaOAuth2Util.checkRightUrl(ra.clientId, ra.redirectUri); - - // 4、校验:此次申请的Scope,该Client是否已经签约 - SaOAuth2Util.checkContract(ra.clientId, ra.scope); - - // 5、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面 - boolean isGrant = SaOAuth2Util.isGrant(ra.loginId, ra.clientId, ra.scope); - if( ! isGrant) { - return cfg.getConfirmView().apply(ra.clientId, ra.scope); - } - - // 6、判断授权类型 - // 如果是 授权码式,则:开始重定向授权,下放code - if(ResponseType.code.equals(ra.responseType)) { - CodeModel codeModel = SaOAuth2Util.generateCode(ra); - 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); - String redirectUri = SaOAuth2Util.buildImplicitRedirectUri(ra.redirectUri, at.accessToken, ra.state); - return res.redirect(redirectUri); - } - - // 默认返回 - throw new SaOAuth2Exception("无效response_type: " + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125); - } - - /** - * Code授权码 获取 Access-Token - * @param req 请求对象 - * @param res 响应对象 - * @param cfg 配置对象 - * @return 处理结果 - */ - public static Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - // 获取参数 - String authorizationValue = SaHttpBasicUtil.getAuthorizationValue(); - String clientId; - String clientSecret; - // gitlab回调token接口时,按照的是标准的oauth2协议的basic请求头,basic中会包含client_id和client_secret的信息 - if(SaFoxUtil.isEmpty(authorizationValue)){ - clientId = req.getParamNotNull(Param.client_id); - clientSecret = req.getParamNotNull(Param.client_secret); - } else { - String[] clientIdAndSecret = authorizationValue.split(":"); - clientId = clientIdAndSecret[0]; - clientSecret = clientIdAndSecret[1]; - } - - String code = req.getParamNotNull(Param.code); - String redirectUri = req.getParam(Param.redirect_uri); - - // 校验参数 - SaOAuth2Util.checkGainTokenParam(code, clientId, clientSecret, redirectUri); - - // 构建 Access-Token - AccessTokenModel token = SaOAuth2Util.generateAccessToken(code); - - // 返回 - return SaResult.data(token.toLineMap()); - } - - /** - * 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返回 - Object data = SaOAuth2Util.refreshAccessToken(refreshToken).toLineMap(); - return SaResult.data(data); - } - - /** - * 回收 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); - - // 回收 Access-Token - SaOAuth2Util.revokeAccessToken(accessToken); - return SaResult.ok(); - } - - /** - * doLogin 登录接口 - * @param req 请求对象 - * @param res 响应对象 - * @param cfg 配置对象 - * @return 处理结果 - */ - public static Object doLogin(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - return cfg.getDoLoginHandle().apply(req.getParamNotNull(Param.name), req.getParamNotNull(Param.pwd)); - } - - /** - * doConfirm 确认授权接口 - * @param req 请求对象 - * @return 处理结果 - */ - public static Object doConfirm(SaRequest req) { - String clientId = req.getParamNotNull(Param.client_id); - String scope = req.getParamNotNull(Param.scope); - Object loginId = StpUtil.getLoginId(); - SaOAuth2Util.saveGrantScope(clientId, loginId, scope); - return SaResult.ok(); - } - - /** - * 模式三:密码式 - * @param req 请求对象 - * @param res 响应对象 - * @param cfg 配置对象 - * @return 处理结果 - */ - public static Object password(SaRequest req, SaResponse res, SaOAuth2Config cfg) { - - // 1、获取请求参数 - String username = req.getParamNotNull(Param.username); - String password = req.getParamNotNull(Param.password); - String clientId = req.getParamNotNull(Param.client_id); - String clientSecret = req.getParamNotNull(Param.client_secret); - String scope = req.getParam(Param.scope, ""); - - // 2、校验 ClientScope 和 scope - SaOAuth2Util.checkClientSecretAndScope(clientId, clientSecret, scope); - - // 3、防止因前端误传token造成逻辑干扰 - // SaHolder.getStorage().set(StpUtil.stpLogic.splicingKeyJustCreatedSave(), "no-token"); - - // 3、调用API 开始登录,如果没能成功登录,则直接退出 - Object retObj = cfg.getDoLoginHandle().apply(username, password); - if( ! StpUtil.isLogin()) { - return retObj; - } - - // 4、构建 ra对象 - RequestAuthModel ra = new RequestAuthModel(); - ra.clientId = clientId; - ra.loginId = StpUtil.getLoginId(); - ra.scope = scope; - - // 5、生成 Access-Token - AccessTokenModel at = SaOAuth2Util.generateAccessToken(ra, true); - - // 6、返回 Access-Token - return SaResult.data(at.toLineMap()); - } - - /** - * 模式四:凭证式 - * @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()); - } - - /** - * 根据当前请求提交的 client_id 参数获取 SaClientModel 对象 - * @return / - */ - public static SaClientModel currClientModel() { - String clientId = SaHolder.getRequest().getParam(Param.client_id); - return SaOAuth2Util.checkClientModel(clientId); - } - -} +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.oauth2.processor; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil; +import cn.dev33.satoken.oauth2.SaOAuth2Manager; +import cn.dev33.satoken.oauth2.config.SaOAuth2Config; +import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; +import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; +import cn.dev33.satoken.oauth2.model.*; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Api; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.GrantType; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.ResponseType; +import cn.dev33.satoken.oauth2.template.SaOAuth2Template; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import cn.dev33.satoken.util.SaResult; + +/** + * Sa-Token OAuth2 请求处理器 + * + * @author click33 + * @since 1.23.0 + */ +public class SaOAuth2ServerProcessor { + + /** + * 全局默认实例 + */ + public static SaOAuth2ServerProcessor instance = new SaOAuth2ServerProcessor(); + + /** + * 底层 SaOAuth2Template 对象 + */ + public SaOAuth2Template oauth2Template = new SaOAuth2Template(); + + /** + * 处理 Server 端请求, 路由分发 + * @return 处理结果 + */ + public Object dister() { + + // 获取变量 + 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)) { + SaClientModel cm = currClientModel(); + if(cfg.getIsCode() && (cm.isCode || cm.isAutoMode)) { + return authorize(req, res, cfg); + } + throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30131); + } + + // 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 + if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) { + return refreshToken(req); + } + + // 回收 Access-Token + if(req.isPath(Api.revoke)) { + return revokeToken(req); + } + + // doLogin 登录接口 + if(req.isPath(Api.doLogin)) { + return doLogin(req, res, cfg); + } + + // doConfirm 确认授权接口 + if(req.isPath(Api.doConfirm)) { + return doConfirm(req); + } + + // 模式二:隐藏式 + if(req.isPath(Api.authorize) && req.isParam(Param.response_type, ResponseType.token)) { + SaClientModel cm = currClientModel(); + if(cfg.getIsImplicit() && (cm.isImplicit || cm.isAutoMode)) { + return authorize(req, res, cfg); + } + throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30132); + } + + // 模式三:密码式 + if(req.isPath(Api.token) && req.isParam(Param.grant_type, GrantType.password)) { + SaClientModel cm = currClientModel(); + if(cfg.getIsPassword() && (cm.isPassword || cm.isAutoMode)) { + return password(req, res, cfg); + } + throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30133); + } + + // 模式四:凭证式 + if(req.isPath(Api.client_token) && req.isParam(Param.grant_type, GrantType.client_credentials)) { + SaClientModel cm = currClientModel(); + if(cfg.getIsClient() && (cm.isClient || cm.isAutoMode)) { + return clientToken(req, res, cfg); + } + throw new SaOAuth2Exception("暂未开放的授权模式").setCode(SaOAuth2ErrorCode.CODE_30134); + } + + // 默认返回 + return SaOAuth2Consts.NOT_HANDLE; + } + + /** + * 模式一:Code授权码 / 模式二:隐藏式 + * @param req 请求对象 + * @param res 响应对象 + * @param cfg 配置对象 + * @return 处理结果 + */ + public Object authorize(SaRequest req, SaResponse res, SaOAuth2Config cfg) { + + // 1、如果尚未登录, 则先去登录 + if( ! StpUtil.isLogin()) { + return cfg.getNotLoginView().get(); + } + + // 2、构建请求Model + RequestAuthModel ra = oauth2Template.generateRequestAuth(req, StpUtil.getLoginId()); + + // 3、校验:重定向域名是否合法 + oauth2Template.checkRightUrl(ra.clientId, ra.redirectUri); + + // 4、校验:此次申请的Scope,该Client是否已经签约 + oauth2Template.checkContract(ra.clientId, ra.scope); + + // 5、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面 + boolean isGrant = oauth2Template.isGrant(ra.loginId, ra.clientId, ra.scope); + if( ! isGrant) { + return cfg.getConfirmView().apply(ra.clientId, ra.scope); + } + + // 6、判断授权类型 + // 如果是 授权码式,则:开始重定向授权,下放code + if(ResponseType.code.equals(ra.responseType)) { + CodeModel codeModel = oauth2Template.generateCode(ra); + String redirectUri = oauth2Template.buildRedirectUri(ra.redirectUri, codeModel.code, ra.state); + return res.redirect(redirectUri); + } + + // 如果是 隐藏式,则:开始重定向授权,下放 token + if(ResponseType.token.equals(ra.responseType)) { + AccessTokenModel at = oauth2Template.generateAccessToken(ra, false); + String redirectUri = oauth2Template.buildImplicitRedirectUri(ra.redirectUri, at.accessToken, ra.state); + return res.redirect(redirectUri); + } + + // 默认返回 + throw new SaOAuth2Exception("无效response_type: " + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125); + } + + /** + * Code授权码 获取 Access-Token + * @param req 请求对象 + * @param res 响应对象 + * @param cfg 配置对象 + * @return 处理结果 + */ + public Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) { + // 获取参数 + String authorizationValue = SaHttpBasicUtil.getAuthorizationValue(); + String clientId; + String clientSecret; + // gitlab回调token接口时,按照的是标准的oauth2协议的basic请求头,basic中会包含client_id和client_secret的信息 + if(SaFoxUtil.isEmpty(authorizationValue)){ + clientId = req.getParamNotNull(Param.client_id); + clientSecret = req.getParamNotNull(Param.client_secret); + } else { + String[] clientIdAndSecret = authorizationValue.split(":"); + clientId = clientIdAndSecret[0]; + clientSecret = clientIdAndSecret[1]; + } + + String code = req.getParamNotNull(Param.code); + String redirectUri = req.getParam(Param.redirect_uri); + + // 校验参数 + oauth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri); + + // 构建 Access-Token + AccessTokenModel token = oauth2Template.generateAccessToken(code); + + // 返回 + return SaResult.data(token.toLineMap()); + } + + /** + * Refresh-Token 刷新 Access-Token + * @param req 请求对象 + * @return 处理结果 + */ + public 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); + + // 校验参数 + oauth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken); + + // 获取新Token返回 + Object data = oauth2Template.refreshAccessToken(refreshToken).toLineMap(); + return SaResult.data(data); + } + + /** + * 回收 Access-Token + * @param req 请求对象 + * @return 处理结果 + */ + public 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(oauth2Template.getAccessToken(accessToken) == null) { + return SaResult.ok("access_token不存在:" + accessToken); + } + + // 校验参数 + oauth2Template.checkAccessTokenParam(clientId, clientSecret, accessToken); + + // 回收 Access-Token + oauth2Template.revokeAccessToken(accessToken); + return SaResult.ok(); + } + + /** + * doLogin 登录接口 + * @param req 请求对象 + * @param res 响应对象 + * @param cfg 配置对象 + * @return 处理结果 + */ + public Object doLogin(SaRequest req, SaResponse res, SaOAuth2Config cfg) { + return cfg.getDoLoginHandle().apply(req.getParamNotNull(Param.name), req.getParamNotNull(Param.pwd)); + } + + /** + * doConfirm 确认授权接口 + * @param req 请求对象 + * @return 处理结果 + */ + public Object doConfirm(SaRequest req) { + String clientId = req.getParamNotNull(Param.client_id); + String scope = req.getParamNotNull(Param.scope); + Object loginId = StpUtil.getLoginId(); + oauth2Template.saveGrantScope(clientId, loginId, scope); + return SaResult.ok(); + } + + /** + * 模式三:密码式 + * @param req 请求对象 + * @param res 响应对象 + * @param cfg 配置对象 + * @return 处理结果 + */ + public Object password(SaRequest req, SaResponse res, SaOAuth2Config cfg) { + + // 1、获取请求参数 + String username = req.getParamNotNull(Param.username); + String password = req.getParamNotNull(Param.password); + String clientId = req.getParamNotNull(Param.client_id); + String clientSecret = req.getParamNotNull(Param.client_secret); + String scope = req.getParam(Param.scope, ""); + + // 2、校验 ClientScope 和 scope + oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scope); + + // 3、防止因前端误传token造成逻辑干扰 + // SaHolder.getStorage().set(StpUtil.stpLogic.splicingKeyJustCreatedSave(), "no-token"); + + // 3、调用API 开始登录,如果没能成功登录,则直接退出 + Object retObj = cfg.getDoLoginHandle().apply(username, password); + if( ! StpUtil.isLogin()) { + return retObj; + } + + // 4、构建 ra对象 + RequestAuthModel ra = new RequestAuthModel(); + ra.clientId = clientId; + ra.loginId = StpUtil.getLoginId(); + ra.scope = scope; + + // 5、生成 Access-Token + AccessTokenModel at = oauth2Template.generateAccessToken(ra, true); + + // 6、返回 Access-Token + return SaResult.data(at.toLineMap()); + } + + /** + * 模式四:凭证式 + * @param req 请求对象 + * @param res 响应对象 + * @param cfg 配置对象 + * @return 处理结果 + */ + public 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 + oauth2Template.checkContract(clientId, scope); + + // 校验 ClientSecret + oauth2Template.checkClientSecret(clientId, clientSecret); + + // 返回 Client-Token + ClientTokenModel ct = oauth2Template.generateClientToken(clientId, scope); + + // 返回 Client-Token + return SaResult.data(ct.toLineMap()); + } + + /** + * 根据当前请求提交的 client_id 参数获取 SaClientModel 对象 + * @return / + */ + public SaClientModel currClientModel() { + String clientId = SaHolder.getRequest().getParam(Param.client_id); + return oauth2Template.checkClientModel(clientId); + } + +} diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java similarity index 98% rename from sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java rename to sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java index 2add96c5..f411e6aa 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Template.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Template.java @@ -13,25 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.dev33.satoken.oauth2.logic; - -import java.util.List; +package cn.dev33.satoken.oauth2.template; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.context.model.SaRequest; import cn.dev33.satoken.oauth2.SaOAuth2Manager; +import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts.Param; import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode; import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param; -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.oauth2.model.*; import cn.dev33.satoken.strategy.SaStrategy; import cn.dev33.satoken.util.SaFoxUtil; +import java.util.List; + /** * Sa-Token-OAuth2 模块 代码实现 * @@ -40,15 +35,17 @@ import cn.dev33.satoken.util.SaFoxUtil; */ public class SaOAuth2Template { - // ------------------- 获取数据 (开发者必须重写的函数) + // ------------------- 数据加载 + /** * 根据id获取Client信息 * @param clientId 应用id * @return ClientModel */ public SaClientModel getClientModel(String clientId) { - return null; + return SaOAuth2Manager.getDataLoader().getClientModel(clientId); } + /** * 根据ClientId 和 LoginId 获取openid * @param clientId 应用id @@ -56,7 +53,7 @@ public class SaOAuth2Template { * @return 此账号在此Client下的openid */ public String getOpenid(String clientId, Object loginId) { - return null; + return SaOAuth2Manager.getDataLoader().getOpenid(clientId, loginId); } // ------------------- 资源校验API diff --git a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Util.java similarity index 72% rename from sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java rename to sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Util.java index 856900d7..25bbfc41 100644 --- a/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/logic/SaOAuth2Util.java +++ b/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/template/SaOAuth2Util.java @@ -13,15 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.dev33.satoken.oauth2.logic; +package cn.dev33.satoken.oauth2.template; import cn.dev33.satoken.context.model.SaRequest; -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.oauth2.model.*; +import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor; /** * Sa-Token-OAuth2 模块 工具类 @@ -30,12 +26,6 @@ import cn.dev33.satoken.oauth2.model.SaClientModel; * @since 1.23.0 */ public class SaOAuth2Util { - - /** - * 模板代码对象 - */ - public static SaOAuth2Template saOAuth2Template = new SaOAuth2Template(); - // ------------------- 资源校验API @@ -45,7 +35,7 @@ public class SaOAuth2Util { * @return ClientModel */ public static SaClientModel checkClientModel(String clientId) { - return saOAuth2Template.checkClientModel(clientId); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientModel(clientId); } /** @@ -54,7 +44,7 @@ public class SaOAuth2Util { * @return . */ public static AccessTokenModel checkAccessToken(String accessToken) { - return saOAuth2Template.checkAccessToken(accessToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkAccessToken(accessToken); } /** @@ -63,7 +53,7 @@ public class SaOAuth2Util { * @return . */ public static ClientTokenModel checkClientToken(String clientToken) { - return saOAuth2Template.checkClientToken(clientToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientToken(clientToken); } /** @@ -72,7 +62,7 @@ public class SaOAuth2Util { * @return LoginId */ public static Object getLoginIdByAccessToken(String accessToken) { - return saOAuth2Template.getLoginIdByAccessToken(accessToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.getLoginIdByAccessToken(accessToken); } /** @@ -81,7 +71,7 @@ public class SaOAuth2Util { * @param scopes 需要校验的权限列表 */ public static void checkScope(String accessToken, String... scopes) { - saOAuth2Template.checkScope(accessToken, scopes); + SaOAuth2ServerProcessor.instance.oauth2Template.checkScope(accessToken, scopes); } /** @@ -90,7 +80,7 @@ public class SaOAuth2Util { * @param scopes 需要校验的权限列表 */ public static void checkClientTokenScope(String clientToken, String... scopes) { - saOAuth2Template.checkClientTokenScope(clientToken, scopes); + SaOAuth2ServerProcessor.instance.oauth2Template.checkClientTokenScope(clientToken, scopes); } // ------------------- generate 构建数据 @@ -102,7 +92,7 @@ public class SaOAuth2Util { * @return RequestAuthModel对象 */ public static RequestAuthModel generateRequestAuth(SaRequest req, Object loginId) { - return saOAuth2Template.generateRequestAuth(req, loginId); + return SaOAuth2ServerProcessor.instance.oauth2Template.generateRequestAuth(req, loginId); } /** @@ -111,7 +101,7 @@ public class SaOAuth2Util { * @return 授权码Model */ public static CodeModel generateCode(RequestAuthModel ra) { - return saOAuth2Template.generateCode(ra); + return SaOAuth2ServerProcessor.instance.oauth2Template.generateCode(ra); } /** @@ -120,7 +110,7 @@ public class SaOAuth2Util { * @return AccessToken Model */ public static AccessTokenModel generateAccessToken(String code) { - return saOAuth2Template.generateAccessToken(code); + return SaOAuth2ServerProcessor.instance.oauth2Template.generateAccessToken(code); } /** @@ -129,7 +119,7 @@ public class SaOAuth2Util { * @return 新的 Access-Token */ public static AccessTokenModel refreshAccessToken(String refreshToken) { - return saOAuth2Template.refreshAccessToken(refreshToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.refreshAccessToken(refreshToken); } /** @@ -139,7 +129,7 @@ public class SaOAuth2Util { * @return Access-Token Model */ public static AccessTokenModel generateAccessToken(RequestAuthModel ra, boolean isCreateRt) { - return saOAuth2Template.generateAccessToken(ra, isCreateRt); + return SaOAuth2ServerProcessor.instance.oauth2Template.generateAccessToken(ra, isCreateRt); } /** @@ -149,7 +139,7 @@ public class SaOAuth2Util { * @return Client-Token Model */ public static ClientTokenModel generateClientToken(String clientId, String scope) { - return saOAuth2Template.generateClientToken(clientId, scope); + return SaOAuth2ServerProcessor.instance.oauth2Template.generateClientToken(clientId, scope); } /** @@ -160,7 +150,7 @@ public class SaOAuth2Util { * @return 构建完毕的URL */ public static String buildRedirectUri(String redirectUri, String code, String state) { - return saOAuth2Template.buildRedirectUri(redirectUri, code, state); + return SaOAuth2ServerProcessor.instance.oauth2Template.buildRedirectUri(redirectUri, code, state); } /** @@ -171,7 +161,7 @@ public class SaOAuth2Util { * @return 构建完毕的URL */ public static String buildImplicitRedirectUri(String redirectUri, String token, String state) { - return saOAuth2Template.buildImplicitRedirectUri(redirectUri, token, state); + return SaOAuth2ServerProcessor.instance.oauth2Template.buildImplicitRedirectUri(redirectUri, token, state); } /** @@ -179,7 +169,7 @@ public class SaOAuth2Util { * @param accessToken Access-Token值 */ public static void revokeAccessToken(String accessToken) { - saOAuth2Template.revokeAccessToken(accessToken); + SaOAuth2ServerProcessor.instance.oauth2Template.revokeAccessToken(accessToken); } // ------------------- 数据校验 @@ -192,7 +182,7 @@ public class SaOAuth2Util { * @return 是否已经授权 */ public static boolean isGrant(Object loginId, String clientId, String scope) { - return saOAuth2Template.isGrant(loginId, clientId, scope); + return SaOAuth2ServerProcessor.instance.oauth2Template.isGrant(loginId, clientId, scope); } /** @@ -201,7 +191,7 @@ public class SaOAuth2Util { * @param scope 权限(多个用逗号隔开) */ public static void checkContract(String clientId, String scope) { - saOAuth2Template.checkContract(clientId, scope); + SaOAuth2ServerProcessor.instance.oauth2Template.checkContract(clientId, scope); } /** @@ -210,7 +200,7 @@ public class SaOAuth2Util { * @param url 指定url */ public static void checkRightUrl(String clientId, String url) { - saOAuth2Template.checkRightUrl(clientId, url); + SaOAuth2ServerProcessor.instance.oauth2Template.checkRightUrl(clientId, url); } /** @@ -220,7 +210,7 @@ public class SaOAuth2Util { * @return SaClientModel对象 */ public static SaClientModel checkClientSecret(String clientId, String clientSecret) { - return saOAuth2Template.checkClientSecret(clientId, clientSecret); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientSecret(clientId, clientSecret); } /** @@ -231,7 +221,7 @@ public class SaOAuth2Util { * @return SaClientModel对象 */ public static SaClientModel checkClientSecretAndScope(String clientId, String clientSecret, String scopes) { - return saOAuth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkClientSecretAndScope(clientId, clientSecret, scopes); } /** @@ -243,7 +233,7 @@ public class SaOAuth2Util { * @return CodeModel对象 */ public static CodeModel checkGainTokenParam(String code, String clientId, String clientSecret, String redirectUri) { - return saOAuth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkGainTokenParam(code, clientId, clientSecret, redirectUri); } /** @@ -254,7 +244,7 @@ public class SaOAuth2Util { * @return CodeModel对象 */ public static RefreshTokenModel checkRefreshTokenParam(String clientId, String clientSecret, String refreshToken) { - return saOAuth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken); } /** @@ -265,7 +255,7 @@ public class SaOAuth2Util { * @return SaClientModel对象 */ public static AccessTokenModel checkAccessTokenParam(String clientId, String clientSecret, String accessToken) { - return saOAuth2Template.checkAccessTokenParam(clientId, clientSecret, accessToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.checkAccessTokenParam(clientId, clientSecret, accessToken); } // ------------------- save 数据 @@ -277,7 +267,7 @@ public class SaOAuth2Util { * @param scope 权限列表(多个逗号隔开) */ public static void saveGrantScope(String clientId, Object loginId, String scope) { - saOAuth2Template.saveGrantScope(clientId, loginId, scope); + SaOAuth2ServerProcessor.instance.oauth2Template.saveGrantScope(clientId, loginId, scope); } @@ -289,7 +279,7 @@ public class SaOAuth2Util { * @return . */ public static CodeModel getCode(String code) { - return saOAuth2Template.getCode(code); + return SaOAuth2ServerProcessor.instance.oauth2Template.getCode(code); } /** @@ -298,7 +288,7 @@ public class SaOAuth2Util { * @return . */ public static AccessTokenModel getAccessToken(String accessToken) { - return saOAuth2Template.getAccessToken(accessToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.getAccessToken(accessToken); } /** @@ -307,7 +297,7 @@ public class SaOAuth2Util { * @return . */ public static RefreshTokenModel getRefreshToken(String refreshToken) { - return saOAuth2Template.getRefreshToken(refreshToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.getRefreshToken(refreshToken); } /** @@ -316,7 +306,7 @@ public class SaOAuth2Util { * @return . */ public static ClientTokenModel getClientToken(String clientToken) { - return saOAuth2Template.getClientToken(clientToken); + return SaOAuth2ServerProcessor.instance.oauth2Template.getClientToken(clientToken); } /** @@ -326,7 +316,7 @@ public class SaOAuth2Util { * @return 权限 */ public static String getGrantScope(String clientId, Object loginId) { - return saOAuth2Template.getGrantScope(clientId, loginId); + return SaOAuth2ServerProcessor.instance.oauth2Template.getGrantScope(clientId, loginId); } } diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/oauth2/SaOAuth2AutoConfigure.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/oauth2/SaOAuth2AutoConfigure.java index 0b01e86e..5c7626c5 100644 --- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/oauth2/SaOAuth2AutoConfigure.java +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/oauth2/SaOAuth2AutoConfigure.java @@ -17,8 +17,8 @@ package cn.dev33.satoken.solon.oauth2; import cn.dev33.satoken.oauth2.SaOAuth2Manager; import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Template; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Util; +import cn.dev33.satoken.oauth2.template.SaOAuth2Template; +import cn.dev33.satoken.oauth2.template.SaOAuth2Util; import org.noear.solon.annotation.Bean; import org.noear.solon.annotation.Condition; import org.noear.solon.annotation.Configuration; diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java index e7629909..a7aa8b24 100644 --- a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java +++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java @@ -15,18 +15,18 @@ */ package cn.dev33.satoken.spring.oauth2; +import cn.dev33.satoken.oauth2.SaOAuth2Manager; +import cn.dev33.satoken.oauth2.config.SaOAuth2Config; +import cn.dev33.satoken.oauth2.dataloader.SaOAuth2DataLoader; +import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor; +import cn.dev33.satoken.oauth2.template.SaOAuth2Template; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import cn.dev33.satoken.oauth2.SaOAuth2Manager; -import cn.dev33.satoken.oauth2.config.SaOAuth2Config; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Template; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Util; -/* - 小提示:如果你在 idea 中运行源码时出现异常:java: 程序包cn.dev33.satoken.oauth2不存在。 - 在项目根目录进入 cmd,执行 mvn package 即可解决 - */ +// 小提示:如果你在 idea 中运行源码时出现异常:java: 程序包cn.dev33.satoken.oauth2不存在。 +// 在项目根目录进入 cmd,执行 mvn package 即可解决 + /** * 注入 Sa-Token-OAuth2 所需要的组件 @@ -54,7 +54,17 @@ public class SaOAuth2BeanInject { */ @Autowired(required = false) public void setSaOAuth2Interface(SaOAuth2Template saOAuth2Template) { - SaOAuth2Util.saOAuth2Template = saOAuth2Template; + SaOAuth2ServerProcessor.instance.oauth2Template = saOAuth2Template; } - + + /** + * 注入 OAuth2 数据加载器 + * + * @param dataLoader / + */ + @Autowired(required = false) + public void setSaOAuth2Interface(SaOAuth2DataLoader dataLoader) { + SaOAuth2Manager.setDataLoader(dataLoader); + } + } diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java index 26ce74cb..2a4a5ed7 100644 --- a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java +++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java @@ -31,7 +31,7 @@ import org.springframework.context.annotation.Bean; public class SaOAuth2BeanRegister { /** - * 获取 OAuth2 配置对象 + * 获取 OAuth2 配置 Bean * * @return 配置对象 */ @@ -40,5 +40,5 @@ public class SaOAuth2BeanRegister { public SaOAuth2Config getSaOAuth2Config() { return new SaOAuth2Config(); } - + } diff --git a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/inject/MySaOAuth2Template.java b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/inject/MySaOAuth2Template.java index a08c90a5..9324cd39 100644 --- a/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/inject/MySaOAuth2Template.java +++ b/sa-token-test/sa-token-springboot-test/src/test/java/cn/dev33/satoken/integrate/configure/inject/MySaOAuth2Template.java @@ -17,7 +17,7 @@ package cn.dev33.satoken.integrate.configure.inject; import org.springframework.stereotype.Component; -import cn.dev33.satoken.oauth2.logic.SaOAuth2Template; +import cn.dev33.satoken.oauth2.template.SaOAuth2Template; /** * 自定义 Sa-OAuth2 模板方法