diff --git a/pom.xml b/pom.xml index f1ea268a5..ab707fcc6 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 1.45.0 - 2.0.0 + 3.0.1 1.85 @@ -396,7 +396,7 @@ - cn.herodotus.opensteward + io.github.windtool JustAuth ${justauth.version} diff --git a/ruoyi-common/ruoyi-common-social/pom.xml b/ruoyi-common/ruoyi-common-social/pom.xml index ca13e2212..c37b61227 100644 --- a/ruoyi-common/ruoyi-common-social/pom.xml +++ b/ruoyi-common/ruoyi-common-social/pom.xml @@ -18,23 +18,10 @@ - cn.herodotus.opensteward + io.github.windtool JustAuth - - - com.alibaba.fastjson2 - fastjson2 - 2.0.60 - - - - - org.dromara - ruoyi-common-json - - org.dromara diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java deleted file mode 100644 index 3e328a9f1..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java +++ /dev/null @@ -1,185 +0,0 @@ -package me.zhyd.oauth.request; - -import com.alibaba.fastjson2.JSONObject; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.config.AuthSource; -import me.zhyd.oauth.constant.Keys; -import me.zhyd.oauth.enums.AuthResponseStatus; -import me.zhyd.oauth.enums.AuthUserGender; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthToken; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.utils.HttpUtils; -import me.zhyd.oauth.utils.StringUtils; -import me.zhyd.oauth.utils.UrlBuilder; - -/** - *

- * 企业微信登录父类 - *

- * - * @author liguanhua (347826496(a)qq.com) - * @since 1.15.9 - */ -public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultRequest { - - /** - * 创建企业微信认证请求。 - * - * @param config 授权配置 - * @param source 授权来源 - */ - public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source) { - super(config, source); - } - - - /** - * 创建企业微信认证请求。 - * - * @param config 授权配置 - * @param source 授权来源 - * @param authStateCache 授权状态缓存 - */ - public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) { - super(config, source, authStateCache); - } - - /** - * 获取企业微信访问令牌。 - * - * @param authCallback 授权回调参数 - * @return 访问令牌 - */ - @Override - public AuthToken getAccessToken(AuthCallback authCallback) { - String response = doGetAuthorizationCode(accessTokenUrl(null)); - - JSONObject object = this.checkResponse(response); - - return AuthToken.builder() - .accessToken(object.getString(Keys.OAUTH2_ACCESS_TOKEN)) - .expireIn(object.getIntValue(Keys.OAUTH2_EXPIRES_IN)) - .code(authCallback.getCode()) - .build(); - } - - /** - * 获取企业微信用户信息。 - * - * @param authToken 访问令牌 - * @return 授权用户信息 - */ - @Override - public AuthUser getUserInfo(AuthToken authToken) { - String response = doGetUserInfo(authToken); - JSONObject object = this.checkResponse(response); - - // 返回 OpenId 或其他,均代表非当前企业用户,不支持 - // https://github.com/justauth/JustAuth/issues/227 修复bug - String userId = null; - if (object.containsKey("userid")) { - userId = object.getString("userid"); - } else if (object.containsKey("UserId")) { - userId = object.getString("UserId"); - } - if (userId == null) { - throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source); - } - String userTicket = object.getString("user_ticket"); - JSONObject userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket); - - return AuthUser.builder() - .rawUserInfo(userDetail) - .username(userDetail.getString(Keys.NAME)) - .nickname(userDetail.getString("alias")) - .avatar(userDetail.getString(Keys.AVATAR)) - .location(userDetail.getString(Keys.OAUTH2_SCOPE__ADDRESS)) - .email(userDetail.getString(Keys.OAUTH2_SCOPE__EMAIL)) - .uuid(userId) - .gender(AuthUserGender.getWechatRealGender(userDetail.getString(Keys.GENDER))) - .token(authToken) - .source(source.toString()) - .build(); - } - - /** - * 校验请求结果 - * - * @param response 请求结果 - * @return 如果请求结果正常,则返回JSONObject - */ - private JSONObject checkResponse(String response) { - JSONObject object = JSONObject.parseObject(response); - - if (object.containsKey(Keys.VARIANT__ERRCODE) && object.getIntValue(Keys.VARIANT__ERRCODE) != 0) { - throw new AuthException(object.getString(Keys.VARIANT__ERRMSG), source); - } - - return object; - } - - - /** - * 返回获取accessToken的url - * - * @param code 授权码 - * @return 返回获取accessToken的url - */ - @Override - protected String accessTokenUrl(String code) { - return UrlBuilder.fromBaseUrl(source.accessToken()) - .queryParam("corpid", config.getClientId()) - .queryParam("corpsecret", config.getClientSecret()) - .build(); - } - - /** - * 返回获取userInfo的url - * - * @param authToken 用户授权后的token - * @return 返回获取userInfo的url - */ - @Override - protected String userInfoUrl(AuthToken authToken) { - return UrlBuilder.fromBaseUrl(source.userInfo()) - .queryParam(Keys.OAUTH2_ACCESS_TOKEN, authToken.getAccessToken()) - .queryParam(Keys.OAUTH2_CODE, authToken.getCode()) - .build(); - } - - /** - * 用户详情 - * - * @param accessToken accessToken - * @param userId 企业内用户id - * @param userTicket 成员票据,用于获取用户信息或敏感信息 - * @return 用户详情 - */ - private JSONObject getUserDetail(String accessToken, String userId, String userTicket) { - // 用户基础信息 - String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get") - .queryParam(Keys.OAUTH2_ACCESS_TOKEN, accessToken) - .queryParam(Keys.USERID, userId) - .build(); - String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody(); - JSONObject userInfo = checkResponse(userInfoResponse); - - // 用户敏感信息 - if (StringUtils.isNotEmpty(userTicket)) { - String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail") - .queryParam(Keys.OAUTH2_ACCESS_TOKEN, accessToken) - .build(); - JSONObject param = new JSONObject(); - param.put("user_ticket", userTicket); - String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, param.toJSONString()).getBody(); - JSONObject userDetail = checkResponse(userDetailResponse); - - userInfo.putAll(userDetail); - } - return userInfo; - } - -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java deleted file mode 100644 index 613473a3c..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java +++ /dev/null @@ -1,139 +0,0 @@ -package me.zhyd.oauth.request; - -import com.alibaba.fastjson2.JSONObject; -import com.xkcoding.http.support.HttpHeader; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.config.AuthDefaultSource; -import me.zhyd.oauth.constant.Keys; -import me.zhyd.oauth.enums.scope.AuthDingTalkScope; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthToken; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.utils.AuthScopeUtils; -import me.zhyd.oauth.utils.GlobalAuthUtils; -import me.zhyd.oauth.utils.HttpUtils; -import me.zhyd.oauth.utils.UrlBuilder; - -import java.util.HashMap; -import java.util.Map; - -/** - * 新版钉钉二维码登录 - * - * @author yadong.zhang (yadong.zhang0415(a)gmail.com) - * @since 1.16.7 - */ -public class AuthDingTalkV2Request extends AuthDefaultRequest { - - /** - * 创建钉钉 V2 认证请求。 - * - * @param config 授权配置 - */ - public AuthDingTalkV2Request(AuthConfig config) { - super(config, AuthDefaultSource.DINGTALK_V2); - } - - /** - * 创建钉钉 V2 认证请求。 - * - * @param config 授权配置 - * @param authStateCache 授权状态缓存 - */ - public AuthDingTalkV2Request(AuthConfig config, AuthStateCache authStateCache) { - super(config, AuthDefaultSource.DINGTALK_V2, authStateCache); - } - - /** - * 生成钉钉 V2 授权地址。 - * - * @param state 授权状态 - * @return 授权地址 - */ - @Override - public String authorize(String state) { - return UrlBuilder.fromBaseUrl(source.authorize()) - .queryParam(Keys.OAUTH2_RESPONSE_TYPE, Keys.OAUTH2_CODE) - .queryParam(Keys.OAUTH2_CLIENT_ID, config.getClientId()) - .queryParam(Keys.OAUTH2_SCOPE, this.getScopes(",", true, AuthScopeUtils.getDefaultScopes(AuthDingTalkScope.values()))) - .queryParam(Keys.OAUTH2_REDIRECT_URI, GlobalAuthUtils.urlEncode(config.getRedirectUri())) - .queryParam("prompt", "consent") - .queryParam("org_type", config.getDingTalkOrgType()) - .queryParam("corpId", config.getDingTalkCorpId()) - .queryParam("exclusiveLogin", config.isDingTalkExclusiveLogin()) - .queryParam("exclusiveCorpId", config.getDingTalkExclusiveCorpId()) - .queryParam(Keys.OAUTH2_STATE, getRealState(state)) - .build(); - } - - /** - * 获取钉钉 V2 访问令牌。 - * - * @param authCallback 授权回调参数 - * @return 访问令牌 - */ - @Override - public AuthToken getAccessToken(AuthCallback authCallback) { - Map params = new HashMap<>(); - params.put("grantType", Keys.OAUTH2_GRANT_TYPE__AUTHORIZATION_CODE); - params.put("clientId", config.getClientId()); - params.put("clientSecret", config.getClientSecret()); - params.put(Keys.OAUTH2_CODE, authCallback.getCode()); - String response = new HttpUtils(config.getHttpConfig()).post(this.source.accessToken(), JSONObject.toJSONString(params)).getBody(); - JSONObject accessTokenObject = JSONObject.parseObject(response); - if (!accessTokenObject.containsKey("accessToken")) { - throw new AuthException(JSONObject.toJSONString(response), source); - } - return AuthToken.builder() - .accessToken(accessTokenObject.getString("accessToken")) - .refreshToken(accessTokenObject.getString("refreshToken")) - .expireIn(accessTokenObject.getIntValue("expireIn")) - .corpId(accessTokenObject.getString("corpId")) - .build(); - } - - /** - * 获取钉钉 V2 用户信息。 - * - * @param authToken 访问令牌 - * @return 授权用户信息 - */ - @Override - public AuthUser getUserInfo(AuthToken authToken) { - HttpHeader header = new HttpHeader(); - header.add("x-acs-dingtalk-access-token", authToken.getAccessToken()); - - String response = new HttpUtils(config.getHttpConfig()).get(this.source.userInfo(), null, header, false).getBody(); - JSONObject object = JSONObject.parseObject(response); - - authToken.setOpenId(object.getString("openId")); - authToken.setUnionId(object.getString("unionId")); - return AuthUser.builder() - .rawUserInfo(object) - .uuid(object.getString("unionId")) - .username(object.getString("nick")) - .nickname(object.getString("nick")) - .avatar(object.getString("avatarUrl")) - .snapshotUser(object.getBooleanValue("visitor")) - .token(authToken) - .source(source.toString()) - .build(); - } - - /** - * 返回获取accessToken的url - * - * @param code 授权码 - * @return 返回获取accessToken的url - */ - protected String accessTokenUrl(String code) { - return UrlBuilder.fromBaseUrl(source.accessToken()) - .queryParam(Keys.OAUTH2_CODE, code) - .queryParam("clientId", config.getClientId()) - .queryParam("clientSecret", config.getClientSecret()) - .queryParam("grantType", Keys.OAUTH2_GRANT_TYPE__AUTHORIZATION_CODE) - .build(); - } -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java index 667be4d2f..a11eb10c7 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java @@ -68,7 +68,7 @@ public class SocialLoginConfigProperties { private String clientOsType; /** - * maxkey 服务器地址 + * 自托管授权服务器地址 */ private String serverUrl; diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java deleted file mode 100644 index a13ca0161..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.dromara.common.social.gitea; - -import cn.hutool.core.lang.Dict; -import cn.hutool.http.HttpRequest; -import cn.hutool.http.HttpResponse; -import lombok.extern.slf4j.Slf4j; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthToken; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.request.AuthDefaultRequest; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.json.utils.JsonUtils; - -/** - * @author lcry - */ -@Slf4j -public class AuthGiteaRequest extends AuthDefaultRequest { - - /** - * 服务器地址。 - */ - public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.gitea.server-url"); - - /** - * 设定归属域 - */ - public AuthGiteaRequest(AuthConfig config) { - super(config, AuthGiteaSource.GITEA); - } - - /** - * 创建 Gitea 认证请求。 - * - * @param config 授权配置 - * @param authStateCache 授权状态缓存 - */ - public AuthGiteaRequest(AuthConfig config, AuthStateCache authStateCache) { - super(config, AuthGiteaSource.GITEA, authStateCache); - } - - /** - * 获取 Gitea 访问令牌。 - * - * @param authCallback 授权回调参数 - * @return 访问令牌 - */ - @Override - public AuthToken getAccessToken(AuthCallback authCallback) { - String body = doPostAuthorizationCode(authCallback.getCode()); - Dict object = JsonUtils.parseMap(body); - // oauth/token 验证异常 - if (object.containsKey("error")) { - throw new AuthException(object.getStr("error_description")); - } - // user 验证异常 - if (object.containsKey("message")) { - throw new AuthException(object.getStr("message")); - } - return AuthToken.builder() - .accessToken(object.getStr("access_token")) - .refreshToken(object.getStr("refresh_token")) - .idToken(object.getStr("id_token")) - .tokenType(object.getStr("token_type")) - .scope(object.getStr("scope")) - .build(); - } - - /** - * 使用授权码换取 Gitea 访问令牌响应。 - * - * @param code 授权码 - * @return 令牌接口响应体 - */ - @Override - protected String doPostAuthorizationCode(String code) { - HttpRequest request = HttpRequest.post(source.accessToken()) - .form("client_id", config.getClientId()) - .form("client_secret", config.getClientSecret()) - .form("grant_type", "authorization_code") - .form("code", code) - .form("redirect_uri", config.getRedirectUri()); - HttpResponse response = request.execute(); - return response.body(); - } - - /** - * 获取 Gitea 用户信息。 - * - * @param authToken 访问令牌 - * @return 授权用户信息 - */ - @Override - public AuthUser getUserInfo(AuthToken authToken) { - String body = doGetUserInfo(authToken); - Dict object = JsonUtils.parseMap(body); - // oauth/token 验证异常 - if (object.containsKey("error")) { - throw new AuthException(object.getStr("error_description")); - } - // user 验证异常 - if (object.containsKey("message")) { - throw new AuthException(object.getStr("message")); - } - return AuthUser.builder() - .uuid(object.getStr("sub")) - .username(object.getStr("name")) - .nickname(object.getStr("preferred_username")) - .avatar(object.getStr("picture")) - .email(object.getStr("email")) - .token(authToken) - .source(source.toString()) - .build(); - } - -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaSource.java deleted file mode 100644 index 201b22308..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaSource.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.dromara.common.social.gitea; - -import me.zhyd.oauth.config.AuthSource; -import me.zhyd.oauth.request.AuthDefaultRequest; - -/** - * gitea Oauth2 默认接口说明 - * - * @author lcry - */ -public enum AuthGiteaSource implements AuthSource { - - /** - * 自己搭建的 gitea 私服 - */ - GITEA { - /** - * 授权的api - */ - @Override - public String authorize() { - return AuthGiteaRequest.SERVER_URL + "/login/oauth/authorize"; - } - - /** - * 获取accessToken的api - */ - @Override - public String accessToken() { - return AuthGiteaRequest.SERVER_URL + "/login/oauth/access_token"; - } - - /** - * 获取用户信息的api - */ - @Override - public String userInfo() { - return AuthGiteaRequest.SERVER_URL + "/login/oauth/userinfo"; - } - - /** - * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest} - */ - @Override - public Class getTargetClass() { - return AuthGiteaRequest.class; - } - - } -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java deleted file mode 100644 index e730d3c05..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.dromara.common.social.maxkey; - -import cn.hutool.core.lang.Dict; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthToken; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.request.AuthDefaultRequest; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.json.utils.JsonUtils; - -/** - * @author 长春叭哥 2023年03月26日 - */ -public class AuthMaxKeyRequest extends AuthDefaultRequest { - - /** - * 服务器地址。 - */ - public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.maxkey.server-url"); - - /** - * 设定归属域 - */ - public AuthMaxKeyRequest(AuthConfig config) { - super(config, AuthMaxKeySource.MAXKEY); - } - - /** - * 创建 MaxKey 认证请求。 - * - * @param config 授权配置 - * @param authStateCache 授权状态缓存 - */ - public AuthMaxKeyRequest(AuthConfig config, AuthStateCache authStateCache) { - super(config, AuthMaxKeySource.MAXKEY, authStateCache); - } - - /** - * 获取 MaxKey 访问令牌。 - * - * @param authCallback 授权回调参数 - * @return 访问令牌 - */ - @Override - public AuthToken getAccessToken(AuthCallback authCallback) { - String body = doPostAuthorizationCode(authCallback.getCode()); - Dict object = JsonUtils.parseMap(body); - // oauth/token 验证异常 - if (object.containsKey("error")) { - throw new AuthException(object.getStr("error_description")); - } - // user 验证异常 - if (object.containsKey("message")) { - throw new AuthException(object.getStr("message")); - } - return AuthToken.builder() - .accessToken(object.getStr("access_token")) - .refreshToken(object.getStr("refresh_token")) - .idToken(object.getStr("id_token")) - .tokenType(object.getStr("token_type")) - .scope(object.getStr("scope")) - .build(); - } - - /** - * 获取 MaxKey 用户信息。 - * - * @param authToken 访问令牌 - * @return 授权用户信息 - */ - @Override - public AuthUser getUserInfo(AuthToken authToken) { - String body = doGetUserInfo(authToken); - Dict object = JsonUtils.parseMap(body); - // oauth/token 验证异常 - if (object.containsKey("error")) { - throw new AuthException(object.getStr("error_description")); - } - // user 验证异常 - if (object.containsKey("message")) { - throw new AuthException(object.getStr("message")); - } - return AuthUser.builder() - .uuid(object.getStr("userId")) - .username(object.getStr("username")) - .nickname(object.getStr("displayName")) - .avatar(object.getStr("avatar_url")) - .blog(object.getStr("web_url")) - .company(object.getStr("organization")) - .location(object.getStr("location")) - .email(object.getStr("email")) - .remark(object.getStr("bio")) - .token(authToken) - .source(source.toString()) - .build(); - } - -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java deleted file mode 100644 index 1ff57f7c5..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dromara.common.social.maxkey; - -import me.zhyd.oauth.config.AuthSource; -import me.zhyd.oauth.request.AuthDefaultRequest; - -/** - * Oauth2 默认接口说明 - * - * @author 长春叭哥 2023年03月26日 - * - */ -public enum AuthMaxKeySource implements AuthSource { - - /** - * 自己搭建的 maxkey 私服 - */ - MAXKEY { - - /** - * 授权的api - */ - @Override - public String authorize() { - return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/authorize"; - } - - /** - * 获取accessToken的api - */ - @Override - public String accessToken() { - return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/token"; - } - - /** - * 获取用户信息的api - */ - @Override - public String userInfo() { - return AuthMaxKeyRequest.SERVER_URL + "/sign/api/oauth/v20/me"; - } - - /** - * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest} - */ - @Override - public Class getTargetClass() { - return AuthMaxKeyRequest.class; - } - - } -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java deleted file mode 100644 index de8c73792..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.dromara.common.social.topiam; - -import cn.hutool.core.codec.Base64; -import cn.hutool.core.lang.Dict; -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.HttpRequest; -import cn.hutool.http.HttpResponse; -import com.xkcoding.http.support.HttpHeader; -import lombok.extern.slf4j.Slf4j; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthToken; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.request.AuthDefaultRequest; -import me.zhyd.oauth.utils.HttpUtils; -import me.zhyd.oauth.utils.UrlBuilder; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.json.utils.JsonUtils; - -import static org.dromara.common.social.topiam.AuthTopIamSource.TOPIAM; - -/** - * TopIAM 认证请求 - * - * @author xlsea - * @since 2024-01-06 - */ -@Slf4j -public class AuthTopIamRequest extends AuthDefaultRequest { - - /** - * 服务器地址。 - */ - public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.topiam.server-url"); - - /** - * 设定归属域 - */ - public AuthTopIamRequest(AuthConfig config) { - super(config, TOPIAM); - } - - /** - * 创建 TopIAM 认证请求。 - * - * @param config 授权配置 - * @param authStateCache 授权状态缓存 - */ - public AuthTopIamRequest(AuthConfig config, AuthStateCache authStateCache) { - super(config, TOPIAM, authStateCache); - } - - /** - * 获取 TopIAM 访问令牌。 - * - * @param authCallback 授权回调参数 - * @return 访问令牌 - */ - @Override - public AuthToken getAccessToken(AuthCallback authCallback) { - String body = doPostAuthorizationCode(authCallback.getCode()); - Dict object = JsonUtils.parseMap(body); - checkResponse(object); - return AuthToken.builder() - .accessToken(object.getStr("access_token")) - .refreshToken(object.getStr("refresh_token")) - .idToken(object.getStr("id_token")) - .tokenType(object.getStr("token_type")) - .scope(object.getStr("scope")) - .build(); - } - - /** - * 获取 TopIAM 用户信息。 - * - * @param authToken 访问令牌 - * @return 授权用户信息 - */ - @Override - public AuthUser getUserInfo(AuthToken authToken) { - String body = doGetUserInfo(authToken); - Dict object = JsonUtils.parseMap(body); - checkResponse(object); - return AuthUser.builder() - .uuid(object.getStr("sub")) - .username(object.getStr("preferred_username")) - .nickname(object.getStr("nickname")) - .avatar(object.getStr("picture")) - .email(object.getStr("email")) - .token(authToken) - .source(source.toString()) - .build(); - } - - /** - * 使用授权码换取 TopIAM 访问令牌响应。 - * - * @param code 授权码 - * @return 令牌接口响应体 - */ - @Override - protected String doPostAuthorizationCode(String code) { - HttpRequest request = HttpRequest.post(source.accessToken()) - .header("Authorization", "Basic " + Base64.encode("%s:%s".formatted(config.getClientId(), config.getClientSecret()))) - .form("grant_type", "authorization_code") - .form("code", code) - .form("redirect_uri", config.getRedirectUri()); - HttpResponse response = request.execute(); - return response.body(); - } - - /** - * 获取 TopIAM 用户信息接口响应。 - * - * @param authToken 访问令牌 - * @return 用户信息响应体 - */ - @Override - protected String doGetUserInfo(AuthToken authToken) { - return new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader() - .add("Content-Type", "application/json") - .add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody(); - } - - /** - * 生成 TopIAM 授权地址。 - * - * @param state 授权状态 - * @return 授权地址 - */ - @Override - public String authorize(String state) { - return UrlBuilder.fromBaseUrl(super.authorize(state)) - .queryParam("scope", StrUtil.join("%20", config.getScopes())) - .build(); - } - - /** - * 校验 TopIAM 接口响应。 - * - * @param object 响应内容 - */ - private static void checkResponse(Dict object) { - // oauth/token 验证异常 - if (object.containsKey("error")) { - throw new AuthException(object.getStr("error_description")); - } - // user 验证异常 - if (object.containsKey("message")) { - throw new AuthException(object.getStr("message")); - } - } - -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java deleted file mode 100644 index 852d7f5cc..000000000 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.common.social.topiam; - -import me.zhyd.oauth.config.AuthSource; -import me.zhyd.oauth.request.AuthDefaultRequest; - -/** - * Oauth2 默认接口说明 - * - * @author xlsea - * @since 2024-01-06 - */ -public enum AuthTopIamSource implements AuthSource { - - /** - * 测试 - */ - TOPIAM { - /** - * 授权的api - */ - @Override - public String authorize() { - return AuthTopIamRequest.SERVER_URL + "/oauth2/auth"; - } - - /** - * 获取accessToken的api - */ - @Override - public String accessToken() { - return AuthTopIamRequest.SERVER_URL + "/oauth2/token"; - } - - /** - * 获取用户信息的api - */ - @Override - public String userInfo() { - return AuthTopIamRequest.SERVER_URL + "/oauth2/userinfo"; - } - - /** - * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest} - */ - @Override - public Class getTargetClass() { - return AuthTopIamRequest.class; - } - - } -} diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index d5723688f..dc2ff4e81 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -10,9 +10,6 @@ import me.zhyd.oauth.request.*; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.social.config.properties.SocialLoginConfigProperties; import org.dromara.common.social.config.properties.SocialProperties; -import org.dromara.common.social.gitea.AuthGiteaRequest; -import org.dromara.common.social.maxkey.AuthMaxKeyRequest; -import org.dromara.common.social.topiam.AuthTopIamRequest; /** * 认证授权工具类 @@ -58,6 +55,7 @@ public class SocialUtils { .clientId(obj.getClientId()) .clientSecret(obj.getClientSecret()) .redirectUri(obj.getRedirectUri()) + .serverUrl(obj.getServerUrl()) .scopes(obj.getScopes()); return switch (source.toLowerCase()) { case "dingtalk" -> new AuthDingTalkV2Request(builder.build(), STATE_CACHE);