From 2de19a38244629ca9db9140a96a197a8cf42aa44 Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Sat, 28 Mar 2020 21:01:41 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E5=90=88=E5=B9=B6https://gitee.co?= =?UTF-8?q?m/yadong.zhang/JustAuth/pulls/10=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BA=AC=E4=B8=9C=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en-US.md | 6 +- README.md | 6 +- bin/version.txt | 2 +- docs/README.md | 4 +- docs/_coverpage.md | 2 +- pom.xml | 2 +- .../zhyd/oauth/config/AuthDefaultSource.java | 28 +++- .../me/zhyd/oauth/request/AuthJdRequest.java | 154 ++++++++++++++++++ .../me/zhyd/oauth/utils/GlobalAuthUtils.java | 47 ++++-- .../java/me/zhyd/oauth/utils/UrlBuilder.java | 11 ++ 10 files changed, 239 insertions(+), 23 deletions(-) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthJdRequest.java diff --git a/README.en-US.md b/README.en-US.md index b7bd8ab..10034fb 100644 --- a/README.en-US.md +++ b/README.en-US.md @@ -6,7 +6,7 @@

- + @@ -15,7 +15,7 @@ - + @@ -97,7 +97,7 @@ These artifacts are available from Maven Central: me.zhyd.oauth JustAuth - 1.14.0 + 1.15.0-alpha ``` - Using JustAuth diff --git a/README.md b/README.md index 289a4ef..e8709e3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- + @@ -15,7 +15,7 @@ - + @@ -97,7 +97,7 @@ JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具 me.zhyd.oauth JustAuth - 1.14.0 + 1.15.0-alpha ``` - 调用api diff --git a/bin/version.txt b/bin/version.txt index 850e742..d547af9 100644 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -1.14.0 +1.15.0-alpha diff --git a/docs/README.md b/docs/README.md index 9cf6c98..6a5dc0e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,7 @@

- + @@ -18,7 +18,7 @@ - + diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 454aac0..255e285 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -1,6 +1,6 @@ ![](_media/justauth@0,25x.png) -# JustAuth 1.14.0 +# JustAuth 1.15.0-alpha 史上最全的整合第三方登录的开源库 diff --git a/pom.xml b/pom.xml index 88151c0..61db110 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.zhyd.oauth JustAuth - 1.14.0 + 1.15.0-alpha JustAuth https://gitee.com/yadong.zhang/JustAuth diff --git a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java index 3a48641..bc20555 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java @@ -731,7 +731,7 @@ public enum AuthDefaultSource implements AuthSource { * * @since 1.14.0 */ - FEISHU{ + FEISHU { @Override public String authorize() { return "https://open.feishu.cn/connect/qrconnect/page/sso/"; @@ -751,5 +751,31 @@ public enum AuthDefaultSource implements AuthSource { public String refresh() { return "https://open.feishu.cn/connect/qrconnect/oauth2/access_token/"; } + }, + /** + * 京东 + * + * @since 1.15.0-alpha + */ + JD { + @Override + public String authorize() { + return "https://open-oauth.jd.com/oauth2/to_login"; + } + + @Override + public String accessToken() { + return "https://open-oauth.jd.com/oauth2/access_token"; + } + + @Override + public String userInfo() { + return "https://api.jd.com/routerjson"; + } + + @Override + public String refresh() { + return "https://open-oauth.jd.com/oauth2/refresh_token"; + } } } diff --git a/src/main/java/me/zhyd/oauth/request/AuthJdRequest.java b/src/main/java/me/zhyd/oauth/request/AuthJdRequest.java new file mode 100644 index 0000000..fe6d410 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthJdRequest.java @@ -0,0 +1,154 @@ +package me.zhyd.oauth.request; + +import com.alibaba.fastjson.JSONObject; +import com.xkcoding.http.HttpUtil; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.config.AuthDefaultSource; +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.AuthResponse; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.utils.GlobalAuthUtils; +import me.zhyd.oauth.utils.UrlBuilder; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; + +/** + * 京东登录 + * link: http://open.jd.com/home/home#/doc/common?listId=717 + * + * @author harry.lee (harryleexyz@qq.com) + * @since + */ +public class AuthJdRequest extends AuthDefaultRequest { + + public AuthJdRequest(AuthConfig config) { + super(config, AuthDefaultSource.JD); + } + + public AuthJdRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthDefaultSource.JD, authStateCache); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + + Map params = new HashMap<>(5); + params.put("app_key", config.getClientId()); + params.put("app_secret", config.getClientSecret()); + params.put("grant_type", "authorization_code"); + params.put("code", authCallback.getCode()); + String response = HttpUtil.post(source.accessToken(), params, false); + JSONObject object = JSONObject.parseObject(response); + + this.checkResponse(object); + + return AuthToken.builder() + .accessToken(object.getString("access_token")) + .expireIn(object.getIntValue("expires_in")) + .refreshToken(object.getString("refresh_token")) + .scope(object.getString("scope")) + .openId(object.getString("open_id")) + .build(); + } + + /** + * link: http://jos.jd.com/api/showTools.htm?id=3051&groupId=106 + * postUrl: https://api.jd.com/routerjson?v=2.0&method=jingdong.user.getUserInfoByOpenId + * &app_key=x&access_token=x&360buy_param_json={"openId":"x"} + * ×tamp=2019-09-11 11:12:26&sign=DB5278CD12443BEA22C5E5EA05A30D2B + * + * @param authToken token信息 + * @return AuthUser + */ + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + UrlBuilder urlBuilder = UrlBuilder.fromBaseUrl(source.userInfo()) + .queryParam("access_token", authToken.getAccessToken()) + .queryParam("app_key", config.getClientId()) + .queryParam("method", "jingdong.user.getUserInfoByOpenId") + .queryParam("360buy_param_json", "{\"openId\":\"" + authToken.getOpenId() + "\"}") + .queryParam("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) + .queryParam("v", "2.0"); + urlBuilder.queryParam("sign", GlobalAuthUtils.generateJdSignature(config.getClientSecret(), urlBuilder.getReadOnlyParams())); + String response = HttpUtil.post(urlBuilder.build(true)); + JSONObject object = JSONObject.parseObject(response); + + this.checkResponse(object); + + JSONObject data = this.getUserDataJsonObject(object); + + return AuthUser.builder() + .uuid(authToken.getOpenId()) + .username(data.getString("nickName")) + .nickname(data.getString("nickName")) + .avatar(data.getString("imageUrl")) + .gender(AuthUserGender.getRealGender(data.getString("gendar"))) + .token(authToken) + .source(source.toString()) + .build(); + } + + /** + * 个人用户无法申请应用 + * 暂时只能参考官网给出的返回结果解析 + * link: https://open.jd.com/home/home#/doc/api?apiCateId=106&apiId=3051&apiName=jingdong.user.getUserInfoByOpenId + * + * @param object 请求返回结果 + * @return data JSONObject + */ + private JSONObject getUserDataJsonObject(JSONObject object) { + return object.getJSONObject("jingdong_user_getUserInfoByOpenId_response") + .getJSONObject("getuserinfobyappidandopenid_result") + .getJSONObject("data"); + } + + @Override + public AuthResponse refresh(AuthToken oldToken) { + Map params = new HashMap<>(5); + params.put("app_key", config.getClientId()); + params.put("app_secret", config.getClientSecret()); + params.put("grant_type", "refresh_token"); + params.put("refresh_token", oldToken.getRefreshToken()); + String response = HttpUtil.post(source.refresh(), params, false); + JSONObject object = JSONObject.parseObject(response); + + this.checkResponse(object); + + return AuthResponse.builder() + .code(AuthResponseStatus.SUCCESS.getCode()) + .data(AuthToken.builder() + .accessToken(object.getString("access_token")) + .expireIn(object.getIntValue("expires_in")) + .refreshToken(object.getString("refresh_token")) + .scope(object.getString("scope")) + .openId(object.getString("open_id")) + .build()) + .build(); + } + + private void checkResponse(JSONObject object) { + if (object.containsKey("error_response")) { + throw new AuthException(object.getJSONObject("error_response").getString("zh_desc")); + } + } + + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(source.authorize()) + .queryParam("app_key", config.getClientId()) + .queryParam("response_type", "code") + .queryParam("redirect_uri", config.getRedirectUri()) + .queryParam("scope", "snsapi_base") + .queryParam("state", getRealState(state)) + .build(); + } + +} diff --git a/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtils.java b/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtils.java index 5dc883a..c0e95f7 100644 --- a/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtils.java +++ b/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtils.java @@ -122,6 +122,9 @@ public class GlobalAuthUtils { * @return str */ public static String parseMapToString(Map params, boolean encode) { + if (null == params || params.isEmpty()) { + return ""; + } List paramList = new ArrayList<>(); params.forEach((k, v) -> { if (null == v) { @@ -208,10 +211,7 @@ public class GlobalAuthUtils { * @return BASE64 encoded signature string */ public static String generateTwitterSignature(Map params, String method, String baseUrl, String apiSecret, String tokenSecret) { - TreeMap map = new TreeMap<>(); - for (Map.Entry e : params.entrySet()) { - map.put(urlEncode(e.getKey()), e.getValue()); - } + TreeMap map = new TreeMap<>(params); String str = parseMapToString(map, true); String baseStr = method.toUpperCase() + "&" + urlEncode(baseUrl) + "&" + urlEncode(str); String signKey = apiSecret + "&" + (StringUtils.isEmpty(tokenSecret) ? "" : tokenSecret); @@ -234,10 +234,7 @@ public class GlobalAuthUtils { * @return Signature */ public static String generateElemeSignature(String appKey, String secret, long timestamp, String action, String token, Map parameters) { - final Map sorted = new TreeMap<>(); - for (Map.Entry entry : parameters.entrySet()) { - sorted.put(entry.getKey(), entry.getValue()); - } + final Map sorted = new TreeMap<>(parameters); sorted.put("app_key", appKey); sorted.put("timestamp", timestamp); StringBuffer string = new StringBuffer(); @@ -250,14 +247,14 @@ public class GlobalAuthUtils { } /** - * MD5加密饿了么请求的Signature + * MD5加密 *

* 代码copy并修改自:https://coding.net/u/napos_openapi/p/eleme-openapi-java-sdk/git/blob/master/src/main/java/eleme/openapi/sdk/utils/SignatureUtil.java * - * @param str 饿了么请求的Signature + * @param str 待加密的字符串 * @return md5 str */ - private static String md5(String str) { + public static String md5(String str) { MessageDigest md = null; StringBuilder buffer = null; try { @@ -274,4 +271,32 @@ public class GlobalAuthUtils { return null == buffer ? "" : buffer.toString(); } + /** + * 生成京东宙斯平台的签名字符串 + * 宙斯签名规则过程如下: + * 将所有请求参数按照字母先后顺序排列,例如将access_token,app_key,method,timestamp,v 排序为access_token,app_key,method,timestamp,v + * 1.把所有参数名和参数值进行拼接,例如:access_tokenxxxapp_keyxxxmethodxxxxxxtimestampxxxxxxvx + * 2.把appSecret夹在字符串的两端,例如:appSecret+XXXX+appSecret + * 3.使用MD5进行加密,再转化成大写 + * link: http://open.jd.com/home/home#/doc/common?listId=890 + * link: https://github.com/pingjiang/jd-open-api-sdk-src/blob/master/src/main/java/com/jd/open/api/sdk/DefaultJdClient.java + * + * @param appSecret 京东应用密钥 + * @param params 签名参数 + * @return 签名后的字符串 + * @since 1.15.0-alpha + */ + public static String generateJdSignature(String appSecret, Map params) { + Map treeMap = new TreeMap<>(params); + StringBuilder signBuilder = new StringBuilder(appSecret); + for (Map.Entry entry : treeMap.entrySet()) { + String name = entry.getKey(); + String value = String.valueOf(entry.getValue()); + if (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) { + signBuilder.append(name).append(value); + } + } + signBuilder.append(appSecret); + return md5(signBuilder.toString()).toUpperCase(); + } } diff --git a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java index 52e08e1..b8d8708 100644 --- a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java +++ b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java @@ -4,6 +4,7 @@ import com.xkcoding.http.util.MapUtil; import com.xkcoding.http.util.StringUtil; import lombok.Setter; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -35,6 +36,16 @@ public class UrlBuilder { return builder; } + /** + * 只读的参数Map + * + * @return unmodifiable Map + * @since 1.15.0-alpha + */ + public Map getReadOnlyParams() { + return Collections.unmodifiableMap(params); + } + /** * 添加参数 * -- GitLab