From 3933b3b7eee9d734c3ee41a44289913ca13a6dd0 Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Fri, 19 Mar 2021 14:37:37 +0800 Subject: [PATCH] =?UTF-8?q?:egg:=20=E5=A2=9E=E5=8A=A0=E9=92=89=E9=92=89?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/zhyd/oauth/config/AuthConfig.java | 2 +- .../zhyd/oauth/config/AuthDefaultSource.java | 21 +++- .../request/AbstractAuthDingtalkRequest.java | 104 ++++++++++++++++++ .../request/AuthDingTalkAccountRequest.java | 22 ++++ .../oauth/request/AuthDingTalkRequest.java | 82 +------------- 5 files changed, 149 insertions(+), 82 deletions(-) create mode 100644 src/main/java/me/zhyd/oauth/request/AbstractAuthDingtalkRequest.java create mode 100644 src/main/java/me/zhyd/oauth/request/AuthDingTalkAccountRequest.java diff --git a/src/main/java/me/zhyd/oauth/config/AuthConfig.java b/src/main/java/me/zhyd/oauth/config/AuthConfig.java index a18ad55..43c2147 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthConfig.java +++ b/src/main/java/me/zhyd/oauth/config/AuthConfig.java @@ -135,7 +135,7 @@ public class AuthConfig { /** * 是否开启 PKCE 模式,该配置仅用于支持 PKCE 模式的平台,针对无服务应用,不推荐使用隐式授权,推荐使用 PKCE 模式 * - * @since 1.16.0 + * @since 1.15.9 */ private boolean pkce; } diff --git a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java index e5d2a29..3896c29 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java @@ -73,7 +73,7 @@ public enum AuthDefaultSource implements AuthSource { } }, /** - * 钉钉 + * 钉钉扫码登录 */ DINGTALK { @Override @@ -91,6 +91,25 @@ public enum AuthDefaultSource implements AuthSource { return "https://oapi.dingtalk.com/sns/getuserinfo_bycode"; } }, + /** + * 钉钉账号登录 + */ + DINGTALK_ACCOUNT { + @Override + public String authorize() { + return "https://oapi.dingtalk.com/connect/oauth2/sns_authorize"; + } + + @Override + public String accessToken() { + return DINGTALK.accessToken(); + } + + @Override + public String userInfo() { + return DINGTALK.userInfo(); + } + }, /** * 百度 */ diff --git a/src/main/java/me/zhyd/oauth/request/AbstractAuthDingtalkRequest.java b/src/main/java/me/zhyd/oauth/request/AbstractAuthDingtalkRequest.java new file mode 100644 index 0000000..9e5de29 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AbstractAuthDingtalkRequest.java @@ -0,0 +1,104 @@ +package me.zhyd.oauth.request; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.config.AuthSource; +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.GlobalAuthUtils; +import me.zhyd.oauth.utils.HttpUtils; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + *

+ * 钉钉登录抽象类,负责处理使用钉钉账号登录第三方网站和扫码登录第三方网站两种钉钉的登录方式 + *

+ * + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @since 1.16.0 + */ +public abstract class AbstractAuthDingtalkRequest extends AuthDefaultRequest { + + public AbstractAuthDingtalkRequest(AuthConfig config, AuthSource source) { + super(config, source); + } + + + public AbstractAuthDingtalkRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) { + super(config, source, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + return AuthToken.builder().accessCode(authCallback.getCode()).build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String code = authToken.getAccessCode(); + JSONObject param = new JSONObject(); + param.put("tmp_auth_code", code); + String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), param.toJSONString()); + JSONObject object = JSON.parseObject(response); + if (object.getIntValue("errcode") != 0) { + throw new AuthException(object.getString("errmsg")); + } + object = object.getJSONObject("user_info"); + AuthToken token = AuthToken.builder() + .openId(object.getString("openid")) + .unionId(object.getString("unionid")) + .build(); + return AuthUser.builder() + .rawUserInfo(object) + .uuid(object.getString("unionid")) + .nickname(object.getString("nick")) + .username(object.getString("nick")) + .gender(AuthUserGender.UNKNOWN) + .source(source.toString()) + .token(token) + .build(); + } + + /** + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} + * + * @param state state 验证授权流程的参数,可以防止csrf + * @return 返回授权地址 + * @since 1.9.3 + */ + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(source.authorize()) + .queryParam("response_type", "code") + .queryParam("appid", config.getClientId()) + .queryParam("scope", "snsapi_login") + .queryParam("redirect_uri", config.getRedirectUri()) + .queryParam("state", getRealState(state)) + .build(); + } + + /** + * 返回获取userInfo的url + * + * @param authToken 用户授权后的token + * @return 返回获取userInfo的url + */ + @Override + protected String userInfoUrl(AuthToken authToken) { + // 根据timestamp, appSecret计算签名值 + String timestamp = System.currentTimeMillis() + ""; + String urlEncodeSignature = GlobalAuthUtils.generateDingTalkSignature(config.getClientSecret(), timestamp); + + return UrlBuilder.fromBaseUrl(source.userInfo()) + .queryParam("signature", urlEncodeSignature) + .queryParam("timestamp", timestamp) + .queryParam("accessKey", config.getClientId()) + .build(); + } + +} diff --git a/src/main/java/me/zhyd/oauth/request/AuthDingTalkAccountRequest.java b/src/main/java/me/zhyd/oauth/request/AuthDingTalkAccountRequest.java new file mode 100644 index 0000000..9d4743a --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthDingTalkAccountRequest.java @@ -0,0 +1,22 @@ +package me.zhyd.oauth.request; + +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.config.AuthDefaultSource; + +/** + * 钉钉账号登录 + * + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @since 1.0.0 + */ +public class AuthDingTalkAccountRequest extends AbstractAuthDingtalkRequest { + + public AuthDingTalkAccountRequest(AuthConfig config) { + super(config, AuthDefaultSource.DINGTALK_ACCOUNT); + } + + public AuthDingTalkAccountRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthDefaultSource.DINGTALK_ACCOUNT, authStateCache); + } +} diff --git a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java index 56e550b..021a255 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java @@ -1,26 +1,16 @@ package me.zhyd.oauth.request; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import me.zhyd.oauth.utils.HttpUtils; import me.zhyd.oauth.cache.AuthStateCache; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.config.AuthDefaultSource; -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.GlobalAuthUtils; -import me.zhyd.oauth.utils.UrlBuilder; /** - * 钉钉登录 + * 钉钉二维码登录 * * @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @since 1.0.0 */ -public class AuthDingTalkRequest extends AuthDefaultRequest { +public class AuthDingTalkRequest extends AbstractAuthDingtalkRequest { public AuthDingTalkRequest(AuthConfig config) { super(config, AuthDefaultSource.DINGTALK); @@ -29,72 +19,4 @@ public class AuthDingTalkRequest extends AuthDefaultRequest { public AuthDingTalkRequest(AuthConfig config, AuthStateCache authStateCache) { super(config, AuthDefaultSource.DINGTALK, authStateCache); } - - @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { - return AuthToken.builder().accessCode(authCallback.getCode()).build(); - } - - @Override - protected AuthUser getUserInfo(AuthToken authToken) { - String code = authToken.getAccessCode(); - JSONObject param = new JSONObject(); - param.put("tmp_auth_code", code); - String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), param.toJSONString()); - JSONObject object = JSON.parseObject(response); - if (object.getIntValue("errcode") != 0) { - throw new AuthException(object.getString("errmsg")); - } - object = object.getJSONObject("user_info"); - AuthToken token = AuthToken.builder() - .openId(object.getString("openid")) - .unionId(object.getString("unionid")) - .build(); - return AuthUser.builder() - .rawUserInfo(object) - .uuid(object.getString("unionid")) - .nickname(object.getString("nick")) - .username(object.getString("nick")) - .gender(AuthUserGender.UNKNOWN) - .source(source.toString()) - .token(token) - .build(); - } - - /** - * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} - * - * @param state state 验证授权流程的参数,可以防止csrf - * @return 返回授权地址 - * @since 1.9.3 - */ - @Override - public String authorize(String state) { - return UrlBuilder.fromBaseUrl(source.authorize()) - .queryParam("response_type", "code") - .queryParam("appid", config.getClientId()) - .queryParam("scope", "snsapi_login") - .queryParam("redirect_uri", config.getRedirectUri()) - .queryParam("state", getRealState(state)) - .build(); - } - - /** - * 返回获取userInfo的url - * - * @param authToken 用户授权后的token - * @return 返回获取userInfo的url - */ - @Override - protected String userInfoUrl(AuthToken authToken) { - // 根据timestamp, appSecret计算签名值 - String timestamp = System.currentTimeMillis() + ""; - String urlEncodeSignature = GlobalAuthUtils.generateDingTalkSignature(config.getClientSecret(), timestamp); - - return UrlBuilder.fromBaseUrl(source.userInfo()) - .queryParam("signature", urlEncodeSignature) - .queryParam("timestamp", timestamp) - .queryParam("accessKey", config.getClientId()) - .build(); - } } -- GitLab