From abcdc105e03b836d92bdf56438b05393ff7998dc Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Wed, 17 Jul 2019 16:51:30 +0800 Subject: [PATCH 01/14] =?UTF-8?q?:memo:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ update.md | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 79fc132..203cf9a 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ + @@ -120,6 +121,7 @@ authRequest.login(callback); | | [AuthMicrosoftRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java) | 参考文档 | | | [AuthMiRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java) | 参考文档 | | | [AuthToutiaoRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java) | 参考文档 | +| | [AuthTeambitionRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTeambitionRequest.java) | 参考文档 | | | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 | _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ diff --git a/update.md b/update.md index fe36738..f285964 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,7 @@ +### 2019/07/17 +1. 优化代码 +2. 集成Teambition登录 + ### 2019/07/16 1. 重构UrlBuilder类 2. 将CSDN相关的类置为`Deprecated`,后续可能会删除,也可能一直保留。毕竟CSDN的openAPI已经不对外开放了。 From a5da3b9765b22816a9f27ad385af2572f4e3dcbf Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 09:27:59 +0800 Subject: [PATCH 02/14] =?UTF-8?q?:twisted=5Frightwards=5Farrows:=20?= =?UTF-8?q?=E5=90=88=E5=B9=B6github=20pr#19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ update.md | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 203cf9a..7469f0c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ + @@ -122,6 +123,7 @@ authRequest.login(callback); | | [AuthMiRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java) | 参考文档 | | | [AuthToutiaoRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java) | 参考文档 | | | [AuthTeambitionRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTeambitionRequest.java) | 参考文档 | +| | [AuthRenrenRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java) | 参考文档 | | | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 | _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ diff --git a/update.md b/update.md index f285964..66ac4a3 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,7 @@ +### 2019/07/18 +1. 合并github上@pengisgood 的pr#19,集成人人 + + ### 2019/07/17 1. 优化代码 2. 集成Teambition登录 From b5d8dbaedef24ddd9fe48173e5ab8e40a77f1532 Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 12:50:57 +0800 Subject: [PATCH 03/14] update contributor --- developer.md | 1 + 1 file changed, 1 insertion(+) diff --git a/developer.md b/developer.md index 0d94b18..d02b93a 100644 --- a/developer.md +++ b/developer.md @@ -3,4 +3,5 @@ - · yadong.zhang : [Github] | [Gitee] | [个人网站] - · yangkai.shen : [Github] | [个人网站] - · skqing : [Gitee] | [个人网站] +- · pengisgood : [Github] | [个人网站] - 千年等一回,我只为等你... From 090d7d366284a7f308bfb7e4a15195644ea1b2b0 Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 14:58:27 +0800 Subject: [PATCH 04/14] integrate Pinterest --- .../java/me/zhyd/oauth/config/AuthSource.java | 20 +++++ .../oauth/request/AuthPinterestRequest.java | 76 +++++++++++++++++++ .../oauth/url/AuthPinterestUrlBuilder.java | 48 ++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java create mode 100644 src/main/java/me/zhyd/oauth/url/AuthPinterestUrlBuilder.java diff --git a/src/main/java/me/zhyd/oauth/config/AuthSource.java b/src/main/java/me/zhyd/oauth/config/AuthSource.java index f408265..029259f 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthSource.java @@ -469,6 +469,26 @@ public enum AuthSource { public String userInfo() { return "https://api.renren.com/v2/user/get"; } + }, + + /** + * Pinterest + */ + PINTEREST { + @Override + public String authorize() { + return "https://api.pinterest.com/oauth"; + } + + @Override + public String accessToken() { + return "https://api.pinterest.com/v1/oauth/token"; + } + + @Override + public String userInfo() { + return "https://api.pinterest.com/v1/me"; + } }; /** diff --git a/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java b/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java new file mode 100644 index 0000000..f6bdcb7 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java @@ -0,0 +1,76 @@ +package me.zhyd.oauth.request; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONObject; +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.model.AuthUserGender; +import me.zhyd.oauth.url.AuthPinterestUrlBuilder; +import me.zhyd.oauth.url.entity.AuthUserInfoEntity; + +import java.util.Objects; + +import static me.zhyd.oauth.config.AuthSource.PINTEREST; + +/** + * Pinterest登录 + * + * @author hongwei.peng (pengisgood(at)gmail(dot)com) + * @version 1.9.0 + * @since 1.9.0 + */ +public class AuthPinterestRequest extends AuthDefaultRequest { + + public AuthPinterestRequest(AuthConfig config) { + super(config, PINTEREST, new AuthPinterestUrlBuilder()); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + String accessTokenUrl = this.urlBuilder.getAccessTokenUrl(authCallback.getCode()); + HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); + JSONObject accessTokenObject = JSONObject.parseObject(response.body()); + if (!response.isOk()) { + throw new AuthException("Unable to get token from Pinterest using code [" + authCallback.getCode() + "]: " + accessTokenObject); + } + + return AuthToken.builder() + .accessToken(accessTokenObject.getString("access_token")) + .tokenType(accessTokenObject.getString("token_type")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String accessToken = authToken.getAccessToken(); + HttpResponse response = HttpRequest.get(this.urlBuilder.getUserInfoUrl(AuthUserInfoEntity.builder() + .accessToken(accessToken) + .build())).execute(); + JSONObject userObj = JSONObject.parseObject(response.body()).getJSONObject("data"); + + return AuthUser.builder() + .uuid(userObj.getString("id")) + .avatar(getAvatarUrl(userObj)) + .username(userObj.getString("username")) + .nickname(userObj.getString("first_name") + " " + userObj.getString("last_name")) + .gender(AuthUserGender.UNKNOWN) + .remark(userObj.getString("bio")) + .token(authToken) + .source(PINTEREST) + .build(); + } + + private String getAvatarUrl(JSONObject userObj) { + // image is a map data structure + JSONObject jsonObject = userObj.getJSONObject("image"); + if (Objects.isNull(jsonObject)) { + return null; + } + return jsonObject.getJSONObject("60x60").getString("url"); + } + +} diff --git a/src/main/java/me/zhyd/oauth/url/AuthPinterestUrlBuilder.java b/src/main/java/me/zhyd/oauth/url/AuthPinterestUrlBuilder.java new file mode 100644 index 0000000..c321479 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/AuthPinterestUrlBuilder.java @@ -0,0 +1,48 @@ +package me.zhyd.oauth.url; + +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthResponseStatus; +import me.zhyd.oauth.url.entity.AuthUserInfoEntity; + +import java.text.MessageFormat; + +import static me.zhyd.oauth.config.AuthSource.PINTEREST; + +/** + * Pinterest相关的URL构建类 + * + * @author hongwei.peng (pengisgood(at)gmail(dot)com) + * @version 1.9.0 + * @since 1.9.0 + */ +public class AuthPinterestUrlBuilder extends AuthDefaultUrlBuilder { + + private static final String PINTEREST_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}"; + private static final String PINTEREST_USER_INFO_PATTERN = "{0}?access_token={1}&fields=id,username,first_name,last_name,bio,image"; + private static final String PINTEREST_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}&scope=read_public"; + + @Override + public String getAccessTokenUrl(String code) { + return MessageFormat.format(PINTEREST_ACCESS_TOKEN_PATTERN, PINTEREST.accessToken(), config.getClientId(), config.getClientSecret(), code); + } + + @Override + public String getUserInfoUrl(AuthUserInfoEntity userInfoEntity) { + return MessageFormat.format(PINTEREST_USER_INFO_PATTERN, PINTEREST.userInfo(), userInfoEntity.getAccessToken()); + } + + @Override + public String getAuthorizeUrl() { + return MessageFormat.format(PINTEREST_AUTHORIZE_PATTERN, PINTEREST.authorize(), config.getClientId(), config.getRedirectUri(), this.getRealState(config.getState())); + } + + @Override + public String getRefreshUrl(String refreshToken) { + throw new AuthException(AuthResponseStatus.UNSUPPORTED); + } + + @Override + public String getRevokeUrl(String accessToken) { + throw new AuthException(AuthResponseStatus.UNSUPPORTED); + } +} From 917239a89a33c92ee39d8e0d5008bf30303cbc4e Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 15:22:52 +0800 Subject: [PATCH 05/14] =?UTF-8?q?:memo:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + pom.xml | 7 ++++++- update.md | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7469f0c..6f3c904 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ authRequest.login(callback); | | [AuthToutiaoRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java) | 参考文档 | | | [AuthTeambitionRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTeambitionRequest.java) | 参考文档 | | | [AuthRenrenRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java) | 参考文档 | +| | [AuthPinterestRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java) | 参考文档 | | | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 | _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ diff --git a/pom.xml b/pom.xml index 5e33204..c0d9d7d 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ - yadong.zhang + Yadong.Zhang yadong.zhang0415@gmail.com https://www.zhyd.me @@ -39,6 +39,11 @@ shenyangkai1994@gmail.com https://xkcoding.com + + Hongwei.Peng + pengisgood@gmail.com + https://github.com/pengisgood + diff --git a/update.md b/update.md index 66ac4a3..12664fb 100644 --- a/update.md +++ b/update.md @@ -1,6 +1,6 @@ ### 2019/07/18 -1. 合并github上@pengisgood 的pr#19,集成人人 - +1. 合并github上[@pengisgood](https://github.com/pengisgood) 的[pr#19](https://github.com/zhangyd-c/JustAuth/pull/19),集成人人 +2. 合并github上[@pengisgood](https://github.com/pengisgood) 的[pr#20](https://github.com/zhangyd-c/JustAuth/pull/20),集成Pinterest ### 2019/07/17 1. 优化代码 From 49f169abb9ab9bad6b047959ef2e6b5eeb757727 Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 15:26:07 +0800 Subject: [PATCH 06/14] =?UTF-8?q?:memo:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f3c904..f982237 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ + From e8cadef4ce6843e747f5a22866877d7ea5c0cfac Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 15:29:16 +0800 Subject: [PATCH 07/14] =?UTF-8?q?:memo:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f982237..cd1c132 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ + + + + From 44d4323fb2226510732c0d095b2ed2149eccd39c Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 15:51:42 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20example.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/example.md b/example.md index 022ca61..fb5f25c 100644 --- a/example.md +++ b/example.md @@ -84,4 +84,12 @@ _注:非全部平台,部分平台可能不存在图例_ 暂无 +#### 授权Pinterest + +![授权Pinterest](https://images.gitee.com/uploads/images/2019/0718/155012_6290f500_784199.jpeg "在这里输入图片标题") + +#### 授权Renren + +![授权Renre](https://images.gitee.com/uploads/images/2019/0718/155035_8e26c10a_784199.jpeg "在这里输入图片标题") + _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ \ No newline at end of file From 698c922b6b370183fc6808ec3ff3e64bb824a91c Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 18:05:22 +0800 Subject: [PATCH 09/14] integrate stack overflow --- example.md | 10 ++- .../java/me/zhyd/oauth/config/AuthConfig.java | 7 ++ .../java/me/zhyd/oauth/config/AuthSource.java | 20 +++++ .../request/AuthStackOverflowRequest.java | 78 +++++++++++++++++++ .../url/AuthStackOverflowUrlBuilder.java | 48 ++++++++++++ 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java create mode 100644 src/main/java/me/zhyd/oauth/url/AuthStackOverflowUrlBuilder.java diff --git a/example.md b/example.md index fb5f25c..8579a12 100644 --- a/example.md +++ b/example.md @@ -84,6 +84,8 @@ _注:非全部平台,部分平台可能不存在图例_ 暂无 +_请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ + #### 授权Pinterest ![授权Pinterest](https://images.gitee.com/uploads/images/2019/0718/155012_6290f500_784199.jpeg "在这里输入图片标题") @@ -92,4 +94,10 @@ _注:非全部平台,部分平台可能不存在图例_ ![授权Renre](https://images.gitee.com/uploads/images/2019/0718/155035_8e26c10a_784199.jpeg "在这里输入图片标题") -_请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ \ No newline at end of file +#### 授权Stack Overflow + +暂无 + +#### 授权Twitter + +暂无 diff --git a/src/main/java/me/zhyd/oauth/config/AuthConfig.java b/src/main/java/me/zhyd/oauth/config/AuthConfig.java index 8b1f7da..57b9656 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthConfig.java +++ b/src/main/java/me/zhyd/oauth/config/AuthConfig.java @@ -51,4 +51,11 @@ public class AuthConfig { * 1.8.0版本新增参数 */ private String state; + + /** + * Stack Overflow Key + *

+ * 1.9.0版本新增参数 + */ + private String stackOverflowKey; } diff --git a/src/main/java/me/zhyd/oauth/config/AuthSource.java b/src/main/java/me/zhyd/oauth/config/AuthSource.java index 029259f..159ce0e 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthSource.java @@ -489,6 +489,26 @@ public enum AuthSource { public String userInfo() { return "https://api.pinterest.com/v1/me"; } + }, + + /** + * Stack Overflow + */ + STACK_OVERFLOW { + @Override + public String authorize() { + return "https://stackoverflow.com/oauth"; + } + + @Override + public String accessToken() { + return "https://stackoverflow.com/oauth/access_token/json"; + } + + @Override + public String userInfo() { + return "https://api.stackexchange.com/2.2/me"; + } }; /** diff --git a/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java new file mode 100644 index 0000000..5f002e7 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java @@ -0,0 +1,78 @@ +package me.zhyd.oauth.request; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONObject; +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.model.AuthUserGender; +import me.zhyd.oauth.url.AuthStackOverflowUrlBuilder; +import me.zhyd.oauth.url.entity.AuthUserInfoEntity; + +import java.util.HashMap; +import java.util.Map; + +import static me.zhyd.oauth.config.AuthSource.STACK_OVERFLOW; + +/** + * Stack Overflow登录 + * + * @author hongwei.peng (pengisgood(at)gmail(dot)com) + * @version 1.9.0 + * @since 1.9.0 + */ +public class AuthStackOverflowRequest extends AuthDefaultRequest { + + public AuthStackOverflowRequest(AuthConfig config) { + super(config, STACK_OVERFLOW, new AuthStackOverflowUrlBuilder()); + } + + @Override + protected AuthToken getAccessToken(AuthCallback authCallback) { + String accessTokenUrl = this.urlBuilder.getAccessTokenUrl(authCallback.getCode()); + HttpResponse response = HttpRequest.post(accessTokenUrl) + .contentType("application/x-www-form-urlencoded") + .form(buildBody(accessTokenUrl)) + .execute(); + JSONObject accessTokenObject = JSONObject.parseObject(response.body()); + if (!response.isOk()) { + throw new AuthException("Unable to get token from Stack Overflow using code [" + authCallback.getCode() + "]: " + accessTokenObject); + } + + return AuthToken.builder() + .accessToken(accessTokenObject.getString("access_token")) + .expireIn(accessTokenObject.getIntValue("expires")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String accessToken = authToken.getAccessToken(); + HttpResponse response = HttpRequest.get(this.urlBuilder.getUserInfoUrl(AuthUserInfoEntity.builder() + .accessToken(accessToken) + .build())).execute(); + JSONObject userObj = JSONObject.parseObject(response.body()).getJSONArray("items").getJSONObject(0); + + return AuthUser.builder() + .uuid(userObj.getString("user_id")) + .avatar(userObj.getString("profile_image")) + .location(userObj.getString("location")) + .nickname(userObj.getString("display_name")) + .blog(userObj.getString("website_url")) + .gender(AuthUserGender.UNKNOWN) + .token(authToken) + .source(STACK_OVERFLOW) + .build(); + } + + private Map buildBody(String accessTokenUrl) { + Map paramMap = new HashMap<>(); + HttpUtil.decodeParamMap(accessTokenUrl, "UTF-8").forEach(paramMap::put); + return paramMap; + } + +} diff --git a/src/main/java/me/zhyd/oauth/url/AuthStackOverflowUrlBuilder.java b/src/main/java/me/zhyd/oauth/url/AuthStackOverflowUrlBuilder.java new file mode 100644 index 0000000..1498e98 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/AuthStackOverflowUrlBuilder.java @@ -0,0 +1,48 @@ +package me.zhyd.oauth.url; + +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthResponseStatus; +import me.zhyd.oauth.url.entity.AuthUserInfoEntity; + +import java.text.MessageFormat; + +import static me.zhyd.oauth.config.AuthSource.STACK_OVERFLOW; + +/** + * Stack Overflow相关的URL构建类 + * + * @author hongwei.peng (pengisgood(at)gmail(dot)com) + * @version 1.9.0 + * @since 1.9.0 + */ +public class AuthStackOverflowUrlBuilder extends AuthDefaultUrlBuilder { + + private static final String SO_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&redirect_uri={3}&code={4}"; + private static final String SO_USER_INFO_PATTERN = "{0}?access_token={1}&site=stackoverflow&key={2}"; + private static final String SO_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}"; + + @Override + public String getAccessTokenUrl(String code) { + return MessageFormat.format(SO_ACCESS_TOKEN_PATTERN, STACK_OVERFLOW.accessToken(), config.getClientId(), config.getClientSecret(), config.getRedirectUri(), code); + } + + @Override + public String getUserInfoUrl(AuthUserInfoEntity userInfoEntity) { + return MessageFormat.format(SO_USER_INFO_PATTERN, STACK_OVERFLOW.userInfo(), userInfoEntity.getAccessToken(), config.getStackOverflowKey()); + } + + @Override + public String getAuthorizeUrl() { + return MessageFormat.format(SO_AUTHORIZE_PATTERN, STACK_OVERFLOW.authorize(), config.getClientId(), config.getRedirectUri(), this.getRealState(config.getState())); + } + + @Override + public String getRefreshUrl(String refreshToken) { + throw new AuthException(AuthResponseStatus.UNSUPPORTED); + } + + @Override + public String getRevokeUrl(String accessToken) { + throw new AuthException(AuthResponseStatus.UNSUPPORTED); + } +} From d0375ce31a8b2cacab1e81900e16406770f0344e Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 18:13:34 +0800 Subject: [PATCH 10/14] update document --- README.md | 3 ++- example.md | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cd1c132..825d7cb 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@

+
@@ -178,4 +179,4 @@ _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经 | 支付宝 | 微信 | | :------------: | :------------: | -| | | \ No newline at end of file +| | | diff --git a/example.md b/example.md index 8579a12..cc87789 100644 --- a/example.md +++ b/example.md @@ -80,12 +80,6 @@ _注:非全部平台,部分平台可能不存在图例_ 暂无 -#### 授权csdn - -暂无 - -_请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ - #### 授权Pinterest ![授权Pinterest](https://images.gitee.com/uploads/images/2019/0718/155012_6290f500_784199.jpeg "在这里输入图片标题") @@ -101,3 +95,9 @@ _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经 #### 授权Twitter 暂无 + +#### 授权csdn + +暂无 + +_请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ From 66ee684e1fa83f67b6c8ae521b4a99eff0681a03 Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 18:23:45 +0800 Subject: [PATCH 11/14] refactor: extract common method --- .../me/zhyd/oauth/request/AuthLinkedinRequest.java | 2 +- .../zhyd/oauth/request/AuthMicrosoftRequest.java | 8 ++++---- .../oauth/request/AuthStackOverflowRequest.java | 14 ++------------ .../java/me/zhyd/oauth/utils/GlobalAuthUtil.java | 7 +++++++ 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java b/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java index 110647f..ac48430 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java @@ -140,7 +140,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest { private AuthToken getToken(String accessTokenUrl) { HttpResponse response = HttpRequest.post(accessTokenUrl) .header("Host", "www.linkedin.com") - .header("Content-Type", "application/x-www-form-urlencoded") + .contentType("application/x-www-form-urlencoded") .execute(); String accessTokenStr = response.body(); JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); diff --git a/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java b/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java index da30f93..71b2129 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java @@ -14,6 +14,8 @@ import me.zhyd.oauth.url.entity.AuthUserInfoEntity; import java.util.HashMap; import java.util.Map; +import static me.zhyd.oauth.utils.GlobalAuthUtil.parseQueryToMap; + /** * 微软登录 * @@ -40,12 +42,10 @@ public class AuthMicrosoftRequest extends AuthDefaultRequest { * @return token对象 */ private AuthToken getToken(String accessTokenUrl) { - Map paramMap = new HashMap<>(6); - HttpUtil.decodeParamMap(accessTokenUrl, "UTF-8").forEach(paramMap::put); HttpResponse response = HttpRequest.post(accessTokenUrl) .header("Host", "https://login.microsoftonline.com") - .header("Content-Type", "application/x-www-form-urlencoded") - .form(paramMap) + .contentType("application/x-www-form-urlencoded") + .form(parseQueryToMap(accessTokenUrl)) .execute(); String accessTokenStr = response.body(); JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); diff --git a/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java index 5f002e7..be5c186 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java @@ -2,7 +2,6 @@ package me.zhyd.oauth.request; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; -import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.exception.AuthException; @@ -13,10 +12,8 @@ import me.zhyd.oauth.model.AuthUserGender; import me.zhyd.oauth.url.AuthStackOverflowUrlBuilder; import me.zhyd.oauth.url.entity.AuthUserInfoEntity; -import java.util.HashMap; -import java.util.Map; - import static me.zhyd.oauth.config.AuthSource.STACK_OVERFLOW; +import static me.zhyd.oauth.utils.GlobalAuthUtil.parseQueryToMap; /** * Stack Overflow登录 @@ -36,7 +33,7 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest { String accessTokenUrl = this.urlBuilder.getAccessTokenUrl(authCallback.getCode()); HttpResponse response = HttpRequest.post(accessTokenUrl) .contentType("application/x-www-form-urlencoded") - .form(buildBody(accessTokenUrl)) + .form(parseQueryToMap(accessTokenUrl)) .execute(); JSONObject accessTokenObject = JSONObject.parseObject(response.body()); if (!response.isOk()) { @@ -68,11 +65,4 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest { .source(STACK_OVERFLOW) .build(); } - - private Map buildBody(String accessTokenUrl) { - Map paramMap = new HashMap<>(); - HttpUtil.decodeParamMap(accessTokenUrl, "UTF-8").forEach(paramMap::put); - return paramMap; - } - } diff --git a/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtil.java b/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtil.java index 22bb699..f313704 100644 --- a/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtil.java +++ b/src/main/java/me/zhyd/oauth/utils/GlobalAuthUtil.java @@ -1,6 +1,7 @@ package me.zhyd.oauth.utils; import cn.hutool.core.codec.Base64; +import cn.hutool.http.HttpUtil; import me.zhyd.oauth.exception.AuthException; import javax.crypto.Mac; @@ -82,6 +83,12 @@ public class GlobalAuthUtil { return res; } + public static Map parseQueryToMap(String url) { + Map paramMap = new HashMap<>(); + HttpUtil.decodeParamMap(url, "UTF-8").forEach(paramMap::put); + return paramMap; + } + public static boolean isHttpProtocol(String url) { if (StringUtils.isEmpty(url)) { return false; From 6dc42ac8b366eae49acd1ba0a653e6a186982766 Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 19:25:23 +0800 Subject: [PATCH 12/14] =?UTF-8?q?:memo:=20=E7=BC=96=E5=86=99=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- update.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 825d7cb..b39e7bb 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ - + @@ -131,6 +131,7 @@ authRequest.login(callback); | | [AuthTeambitionRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTeambitionRequest.java) | 参考文档 | | | [AuthRenrenRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java) | 参考文档 | | | [AuthPinterestRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java) | 参考文档 | +| | [AuthStackOverflowRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java) | 参考文档 | | | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 | _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_ diff --git a/update.md b/update.md index 12664fb..60e02b7 100644 --- a/update.md +++ b/update.md @@ -1,6 +1,7 @@ ### 2019/07/18 1. 合并github上[@pengisgood](https://github.com/pengisgood) 的[pr#19](https://github.com/zhangyd-c/JustAuth/pull/19),集成人人 2. 合并github上[@pengisgood](https://github.com/pengisgood) 的[pr#20](https://github.com/zhangyd-c/JustAuth/pull/20),集成Pinterest +2. 合并github上[@pengisgood](https://github.com/pengisgood) 的[pr#21](https://github.com/zhangyd-c/JustAuth/pull/21),集成StackOverflow ### 2019/07/17 1. 优化代码 From a6f25ec31236ab36b689b7f58346e6b12f8afa7e Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Thu, 18 Jul 2019 19:27:08 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20example.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/example.md b/example.md index cc87789..02e2022 100644 --- a/example.md +++ b/example.md @@ -82,15 +82,15 @@ _注:非全部平台,部分平台可能不存在图例_ #### 授权Pinterest -![授权Pinterest](https://images.gitee.com/uploads/images/2019/0718/155012_6290f500_784199.jpeg "在这里输入图片标题") +![授权Pinterest](https://images.gitee.com/uploads/images/2019/0718/155012_6290f500_784199.jpeg "授权Pinterest") #### 授权Renren -![授权Renre](https://images.gitee.com/uploads/images/2019/0718/155035_8e26c10a_784199.jpeg "在这里输入图片标题") +![授权Renre](https://images.gitee.com/uploads/images/2019/0718/155035_8e26c10a_784199.jpeg "授权Renren") #### 授权Stack Overflow -暂无 +![授权Stack Overflow](https://images.gitee.com/uploads/images/2019/0718/192639_cc301ba7_784199.png "授权Stack Overflow") #### 授权Twitter From 9aa693d2da6a19f52980d58afbd7c8afa033eee9 Mon Sep 17 00:00:00 2001 From: Hongwei Peng Date: Thu, 18 Jul 2019 21:06:03 +0800 Subject: [PATCH 14/14] add refresh token method --- .../zhyd/oauth/request/AuthRenrenRequest.java | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java b/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java index dc74e89..8468958 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java @@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSONObject; import me.zhyd.oauth.config.AuthConfig; 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.model.AuthUserGender; @@ -16,6 +17,7 @@ import me.zhyd.oauth.url.entity.AuthUserInfoEntity; import java.util.Objects; import static me.zhyd.oauth.config.AuthSource.RENREN; +import static me.zhyd.oauth.model.AuthResponseStatus.SUCCESS; /** * 人人登录 @@ -32,26 +34,14 @@ public class AuthRenrenRequest extends AuthDefaultRequest { @Override protected AuthToken getAccessToken(AuthCallback authCallback) { - String accessTokenUrl = this.urlBuilder.getAccessTokenUrl(authCallback.getCode()); - HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); - JSONObject accessTokenObject = JSONObject.parseObject(response.body()); - if (!response.isOk()) { - throw new AuthException("Unable to get token from renren using code [" + authCallback.getCode() + "]: " + accessTokenObject); - } - - return AuthToken.builder() - .accessToken(accessTokenObject.getString("access_token")) - .refreshToken(accessTokenObject.getString("refresh_token")) - .openId(accessTokenObject.getJSONObject("user").getString("id")) - .build(); + return getToken(this.urlBuilder.getAccessTokenUrl(authCallback.getCode())); } @Override protected AuthUser getUserInfo(AuthToken authToken) { - String accessToken = authToken.getAccessToken(); HttpResponse response = HttpRequest.get(this.urlBuilder.getUserInfoUrl(AuthUserInfoEntity.builder() .openId(authToken.getOpenId()) - .accessToken(accessToken) + .accessToken(authToken.getAccessToken()) .build())).execute(); JSONObject userObj = JSONObject.parseObject(response.body()).getJSONObject("response"); @@ -66,6 +56,30 @@ public class AuthRenrenRequest extends AuthDefaultRequest { .build(); } + @Override + public AuthResponse refresh(AuthToken authToken) { + return AuthResponse.builder() + .code(SUCCESS.getCode()) + .data(getToken(this.urlBuilder.getRefreshUrl(authToken.getRefreshToken()))) + .build(); + } + + private AuthToken getToken(String url) { + HttpResponse response = HttpRequest.post(url).execute(); + JSONObject jsonObject = JSONObject.parseObject(response.body()); + if (!response.isOk()) { + throw new AuthException("Failed to get token from Renren: " + jsonObject); + } + + return AuthToken.builder() + .tokenType(jsonObject.getString("token_type")) + .expireIn(jsonObject.getIntValue("expires_in")) + .accessToken(jsonObject.getString("access_token")) + .refreshToken(jsonObject.getString("refresh_token")) + .openId(jsonObject.getJSONObject("user").getString("id")) + .build(); + } + private String getAvatarUrl(JSONObject userObj) { JSONArray jsonArray = userObj.getJSONArray("avatar"); if (Objects.isNull(jsonArray) || jsonArray.isEmpty()) {