From de273d0482193b7bf3fc5e06b03b24b31b0236ec Mon Sep 17 00:00:00 2001 From: shahuang Date: Fri, 30 Aug 2019 16:28:43 +0800 Subject: [PATCH] add kujiale auth --- pom.xml | 2 +- .../java/me/zhyd/oauth/config/AuthSource.java | 26 ++++ .../java/me/zhyd/oauth/model/AuthUser.java | 14 ++ .../oauth/request/AuthKujialeRequest.java | 140 ++++++++++++++++++ 4 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthKujialeRequest.java diff --git a/pom.xml b/pom.xml index e1ead62..7da8895 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ JustAuth https://gitee.com/yadong.zhang/JustAuth - 史上最全的整合第三方登录的工具,目前已支持Github、Gitee、微博、钉钉、百度、Coding、腾讯云开发者平台、OSChina、支付宝、QQ、微信、淘宝、Google、Facebook、抖音、领英、小米、微软和今日头条等第三方平台的授权登录。 + 史上最全的整合第三方登录的工具,目前已支持Github、Gitee、酷家乐、微博、钉钉、百度、Coding、腾讯云开发者平台、OSChina、支付宝、QQ、微信、淘宝、Google、Facebook、抖音、领英、小米、微软和今日头条等第三方平台的授权登录。 Login, so easy! diff --git a/src/main/java/me/zhyd/oauth/config/AuthSource.java b/src/main/java/me/zhyd/oauth/config/AuthSource.java index 3cd14a1..4ba6599 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthSource.java @@ -567,6 +567,32 @@ public enum AuthSource { public String userInfo() { return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo"; } + }, + /** + * 酷家乐 + * + * @since 1.10.1 + */ + KUJIALE { + @Override + public String authorize() { + return "https://oauth.kujiale.com/oauth2/show"; + } + + @Override + public String accessToken() { + return "https://oauth.kujiale.com/oauth2/auth/token"; + } + + @Override + public String userInfo() { + return "https://oauth.kujiale.com/oauth2/openapi/user"; + } + + @Override + public String refresh() { + return "https://oauth.kujiale.com/oauth2/auth/token/refresh"; + } }; /** diff --git a/src/main/java/me/zhyd/oauth/model/AuthUser.java b/src/main/java/me/zhyd/oauth/model/AuthUser.java index 5908075..2604dc6 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthUser.java +++ b/src/main/java/me/zhyd/oauth/model/AuthUser.java @@ -66,4 +66,18 @@ public class AuthUser { * 用户授权的token信息 */ private AuthToken token; + + /** + * 用户在平台上的用户类型(类似是C类用户或者B类用户,或者各个平台自己的细分分类) + */ + private Integer userType; + /** + * 在平台上是否为VIP + */ + private Boolean isVip; + + /** + * 所属平台组织的唯一识别id + */ + private String organizationUuid; } diff --git a/src/main/java/me/zhyd/oauth/request/AuthKujialeRequest.java b/src/main/java/me/zhyd/oauth/request/AuthKujialeRequest.java new file mode 100644 index 0000000..b65d403 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthKujialeRequest.java @@ -0,0 +1,140 @@ +package me.zhyd.oauth.request; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +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.AuthResponseStatus; +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.StringUtils; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + * @author shahuang + * @Date: 2019/8/29 18:50 + * @since 1.10.1 + */ +public class AuthKujialeRequest extends AuthDefaultRequest { + + public AuthKujialeRequest(AuthConfig config) { + super(config, AuthSource.KUJIALE); + } + + public AuthKujialeRequest(AuthConfig config, AuthStateCache authStateCache) { + super(config, AuthSource.KUJIALE, authStateCache); + } + + /** + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} + * 默认只向用户请求用户信息授权 + * @param state state 验证授权流程的参数,可以防止csrf + * @return 返回授权地址 + * @since 1.10.1 + */ + @Override + public String authorize(String state) { + return authorize(state, "get_user_info"); + } + + /** + * 请求授权url + * @param state state 验证授权流程的参数,可以防止csrf + * @param scopeStr 请求用户授权时向用户显示的可进行授权的列表。如果要填写多个接口名称,请用逗号隔开 + * 参考https://open.kujiale.com/open/apps/2/docs?doc_id=95#Step1%EF%BC%9A%E8%8E%B7%E5%8F%96Authorization%20Code参数表内的scope字段 + * @return + */ + public String authorize(String state, String scopeStr) { + UrlBuilder urlBuilder = UrlBuilder.fromBaseUrl(source.authorize()) + .queryParam("response_type", "code") + .queryParam("client_id", config.getClientId()) + .queryParam("redirect_uri", config.getRedirectUri()) + .queryParam("state", getRealState(state)); + if (StringUtils.isNotEmpty(scopeStr)) { + urlBuilder.queryParam("scope", scopeStr); + } + return urlBuilder.build(); + } + + @Override + public AuthToken getAccessToken(AuthCallback authCallback) { + HttpResponse response = doPostAuthorizationCode(authCallback.getCode()); + return getAuthToken(response); + } + + private AuthToken getAuthToken(HttpResponse response) { + String accessTokenStr = response.body(); + JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); + if (!"0".equals(accessTokenObject.getString("c"))) { + throw new AuthException(accessTokenObject.getString("m")); + } + JSONObject resultObject = accessTokenObject.getJSONObject("d"); + return AuthToken.builder() + .accessToken(resultObject.getString("accessToken")) + .refreshToken(resultObject.getString("refreshToken")) + .expireIn(resultObject.getIntValue("expiresIn")) + .build(); + } + + @Override + public AuthUser getUserInfo(AuthToken authToken) { + String openId = this.getOpenId(authToken); + HttpResponse response = HttpRequest.get(UrlBuilder.fromBaseUrl(source.userInfo()) + .queryParam("access_token", authToken.getAccessToken()) + .queryParam("open_id", openId) + .build()).execute(); + JSONObject object = JSONObject.parseObject(response.body()); + if (!"0".equals(object.getString("c"))) { + throw new AuthException(object.getString("m")); + } + JSONObject resultObject = object.getJSONObject("d"); + + JSONObject extraInfoObject = object.getJSONObject("extraInfo"); + boolean isVip = false; + String organizationUuid = null; + if (extraInfoObject != null) { + isVip = extraInfoObject.getBoolean("isVip"); + organizationUuid = extraInfoObject.getString("partnerId"); + } + + return AuthUser.builder() + .username(resultObject.getString("userName")) + .nickname(resultObject.getString("userName")) + .avatar(resultObject.getString("avatar")) + .uuid(resultObject.getString("openId")) + .isVip(isVip) + .organizationUuid(organizationUuid) + .token(authToken) + .source(source) + .build(); + } + + /** + * 获取酷家乐的openId,此id在当前client范围内可以唯一识别授权用户 + * + * @param authToken 通过{@link AuthKujialeRequest#getAccessToken(AuthCallback)}获取到的{@code authToken} + * @return openId + */ + private String getOpenId(AuthToken authToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.fromBaseUrl("https://oauth.kujiale.com/oauth2/auth/user") + .queryParam("access_token", authToken.getAccessToken()) + .build()).execute(); + String accessTokenStr = response.body(); + JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); + if (!"0".equals(accessTokenObject.getString("c"))) { + throw new AuthException(accessTokenObject.getString("m")); + } + return accessTokenObject.getString("d"); + } + + @Override + public AuthResponse refresh(AuthToken authToken) { + HttpResponse response = HttpRequest.post(refreshTokenUrl(authToken.getRefreshToken())).execute(); + return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(getAuthToken(response)).build(); + } +} -- GitLab