From 368cd0460e437f738362ea9adc4254ad8b884b98 Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Wed, 20 Feb 2019 13:14:14 +0800 Subject: [PATCH] =?UTF-8?q?:alien:=20=E9=87=8D=E6=9E=84AuthRequest?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0=E6=96=B9=E5=BC=8F=E3=80=81=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E7=99=BE=E5=BA=A6=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 47 +++++++++++--- .../me/zhyd/oauth/consts/ApiUrlConst.java | 20 ++++++ .../zhyd/oauth/exception/AuthException.java | 22 ++++--- .../zhyd/oauth/model/AuthBaiduErrorCode.java | 62 ++++++++++++++++++ ...orCode.java => AuthDingTalkErrorCode.java} | 10 +-- .../me/zhyd/oauth/model/AuthResponse.java | 5 +- .../java/me/zhyd/oauth/model/AuthSource.java | 4 +- .../java/me/zhyd/oauth/model/AuthUser.java | 1 + .../zhyd/oauth/request/AuthBaiduRequest.java | 63 +++++++++++++++++++ .../oauth/request/AuthDingTalkRequest.java | 44 +++++-------- .../zhyd/oauth/request/AuthGiteeRequest.java | 60 +++++++----------- .../zhyd/oauth/request/AuthGithubRequest.java | 56 ++++++----------- .../me/zhyd/oauth/request/AuthRequest.java | 12 +++- .../zhyd/oauth/request/AuthWeiboRequest.java | 54 ++++++---------- .../zhyd/oauth/request/BaseAuthRequest.java | 60 +++++++++++++++++- .../me/zhyd/oauth/request/ResponseStatus.java | 1 + .../java/me/zhyd/oauth/utils/UrlBuilder.java | 56 +++++++++++++++-- 17 files changed, 410 insertions(+), 167 deletions(-) create mode 100644 src/main/java/me/zhyd/oauth/model/AuthBaiduErrorCode.java rename src/main/java/me/zhyd/oauth/model/{AuthDIngTalkErrorCode.java => AuthDingTalkErrorCode.java} (99%) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java diff --git a/README.md b/README.md index cbffbd3..89e7492 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ - + + @@ -34,8 +35,9 @@ Gitee Github Weibo - CSDN 钉钉 + 百度 + CSDN QQ 微信 @@ -75,10 +77,41 @@ authRequest.login("code"); #### API列表 | :computer: 平台 | :coffee: API类 | :page_facing_up: SDK | |:------:|:-------:|:-------:| -| | [AuthGiteeRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [https://github.com/settings/developers](https://github.com/settings/developers) | -| | [AuthGithubRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [https://gitee.com/api/v5/oauth_doc#list_1](https://gitee.com/api/v5/oauth_doc#list_1) | -| | [AuthWeiboRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [https://open.weibo.com/apps](https://open.weibo.com/apps) | -| | AuthCsdnRequest | [https://connect.qq.com/](https://connect.qq.com/) | -| | [AuthDingTalkRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java) | [https://open-doc.dingtalk.com/microapp/serverapi2/kymkv6](https://open-doc.dingtalk.com/microapp/serverapi2/kymkv6) | +| | [AuthGiteeRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [参考文档](https://github.com/settings/developers) | +| | [AuthGithubRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [参考文档](https://gitee.com/api/v5/oauth_doc#list_1) | +| | [AuthWeiboRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [参考文档](https://open.weibo.com/apps) | +| | [AuthDingTalkRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java) | [参考文档](https://open-doc.dingtalk.com/microapp/serverapi2/kymkv6) | +| | [AuthBaiduRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java) | [参考文档](https://developer.baidu.com/) | +| | AuthCsdnRequest | [参考文档](https://connect.qq.com/) | | | AuthQqRequest | 待续 | | | AuthWechatRequest | 待续 | + +### 参考图例 + +##### Gitee + +待续 + +##### Github + +待续 + +##### Weibo + +待续 + +##### 钉钉 + +待续 + +##### 百度 + +待续 + +##### CSDN + +待续 + +##### 微信 + +待续 diff --git a/src/main/java/me/zhyd/oauth/consts/ApiUrlConst.java b/src/main/java/me/zhyd/oauth/consts/ApiUrlConst.java index 22a0548..82ff825 100644 --- a/src/main/java/me/zhyd/oauth/consts/ApiUrlConst.java +++ b/src/main/java/me/zhyd/oauth/consts/ApiUrlConst.java @@ -66,4 +66,24 @@ public class ApiUrlConst { */ public static final String DING_TALK_USER_INFO_URL = "https://oapi.dingtalk.com/sns/getuserinfo_bycode"; + /** + * 获取baidu access_token的地址 + */ + public static final String BAIDU_ACCESS_TOKEN_URL = "https://openapi.baidu.com/oauth/2.0/token"; + + /** + * 获取baidu用户信息的地址 + */ + public static final String BAIDU_USER_INFO_URL = "https://openapi.baidu.com/rest/2.0/passport/users/getInfo"; + + /** + * 获取baidu授权地址 + */ + public static final String BAIDU_AUTHORIZE_URL = "https://openapi.baidu.com/oauth/2.0/authorize"; + + /** + * 收回baidu授权的地址 + */ + public static final String BAIDU_REVOKE_URL = "https://openapi.baidu.com/rest/2.0/passport/auth/revokeAuthorization"; + } diff --git a/src/main/java/me/zhyd/oauth/exception/AuthException.java b/src/main/java/me/zhyd/oauth/exception/AuthException.java index a7a6c8f..9e1111d 100644 --- a/src/main/java/me/zhyd/oauth/exception/AuthException.java +++ b/src/main/java/me/zhyd/oauth/exception/AuthException.java @@ -10,12 +10,18 @@ import me.zhyd.oauth.request.ResponseStatus; * @since 1.8 */ public class AuthException extends RuntimeException { - public AuthException() { - super(); + + private int errorCode; + private String errorMsg; + + public AuthException(String errorMsg) { + this(ResponseStatus.FAILURE.getCode(), errorMsg); } - public AuthException(String message) { - super(message); + public AuthException(int errorCode, String errorMsg) { + super(errorCode + ":" + errorMsg); + this.errorCode = errorCode; + this.errorMsg = errorMsg; } public AuthException(ResponseStatus status) { @@ -26,11 +32,11 @@ public class AuthException extends RuntimeException { super(message, cause); } - public AuthException(Throwable cause) { - super(cause); + public int getErrorCode() { + return errorCode; } - protected AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); + public String getErrorMsg() { + return errorMsg; } } diff --git a/src/main/java/me/zhyd/oauth/model/AuthBaiduErrorCode.java b/src/main/java/me/zhyd/oauth/model/AuthBaiduErrorCode.java new file mode 100644 index 0000000..13c389e --- /dev/null +++ b/src/main/java/me/zhyd/oauth/model/AuthBaiduErrorCode.java @@ -0,0 +1,62 @@ +package me.zhyd.oauth.model; + +import me.zhyd.oauth.utils.StringUtils; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @website https://www.zhyd.me + * @date 2019/2/19 19:13 + * @since 1.8 + */ +public enum AuthBaiduErrorCode { + OK("ok", "ok", "ok"), + INVALID_REQUEST("invalid_request", "invalid refresh token", "请求缺少某个必需参数,包含一个不支持的参数或参数值,或者格式不正确。"), + INVALID_CLIENT("invalid_client", "unknown client id", "client_id”、“client_secret”参数无效。"), + INVALID_GRANT("invalid_grant", "The provided authorization grant is revoked", "提供的Access Grant是无效的、过期的或已撤销的,例如,Authorization Code无效(一个授权码只能使用一次)、Refresh Token无效、redirect_uri与获取Authorization Code时提供的不一致、Devie Code无效(一个设备授权码只能使用一次)等。"), + UNAUTHORIZED_CLIENT("unauthorized_client", "The client is not authorized to use this authorization grant type", "应用没有被授权,无法使用所指定的grant_type。"), + UNSUPPORTED_GRANT_TYPE("unsupported_grant_type", "The authorization grant type is not supported", "“grant_type”百度OAuth2.0服务不支持该参数。"), + INVALID_SCOPE("invalid_scope", "The requested scope is exceeds the scope granted by the resource owner", "请求的“scope”参数是无效的、未知的、格式不正确的、或所请求的权限范围超过了数据拥有者所授予的权限范围。"), + EXPIRED_TOKEN("expired_token", "refresh token has been used", "提供的Refresh Token已过期"), + REDIRECT_URI_MISMATCH("redirect_uri_mismatch", "Invalid redirect uri", "“redirect_uri”所在的根域与开发者注册应用时所填写的根域名不匹配。"), + UNSUPPORTED_RESPONSE_TYPE("unsupported_response_type", "The response type is not supported", "“response_type”参数值不为百度OAuth2.0服务所支持,或者应用已经主动禁用了对应的授权模式"), + SLOW_DOWN("slow_down", "The device is polling too frequently", "Device Flow中,设备通过Device Code换取Access Token的接口过于频繁,两次尝试的间隔应大于5秒。"), + AUTHORIZATION_PENDING("authorization_pending", "User has not yet completed the authorization", "Device Flow中,用户还没有对Device Code完成授权操作。"), + AUTHORIZATION_DECLINED("authorization_declined", "User has declined the authorization", "Device Flow中,用户拒绝了对Device Code的授权操作。"), + INVALID_REFERER("invalid_referer", "Invalid Referer", "Implicit Grant模式中,浏览器请求的Referer与根域名绑定不匹配"); + + private String code; + private String msg; + private String desc; + + AuthBaiduErrorCode(String code, String msg, String desc) { + this.code = code; + this.msg = msg; + this.desc = desc; + } + + public static AuthBaiduErrorCode getErrorCode(String code) { + if (StringUtils.isEmpty(code)) { + return OK; + } + AuthBaiduErrorCode[] errorCodes = AuthBaiduErrorCode.values(); + for (AuthBaiduErrorCode errorCode : errorCodes) { + if (code.equalsIgnoreCase(errorCode.getCode())) { + return errorCode; + } + } + return OK; + } + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/me/zhyd/oauth/model/AuthDIngTalkErrorCode.java b/src/main/java/me/zhyd/oauth/model/AuthDingTalkErrorCode.java similarity index 99% rename from src/main/java/me/zhyd/oauth/model/AuthDIngTalkErrorCode.java rename to src/main/java/me/zhyd/oauth/model/AuthDingTalkErrorCode.java index 93d5b89..5ff52ff 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthDIngTalkErrorCode.java +++ b/src/main/java/me/zhyd/oauth/model/AuthDingTalkErrorCode.java @@ -7,7 +7,7 @@ package me.zhyd.oauth.model; * @date 2019/2/19 9:42 * @since 1.8 */ -public enum AuthDIngTalkErrorCode { +public enum AuthDingTalkErrorCode { /** * 异常状态码 */ @@ -377,15 +377,15 @@ public enum AuthDIngTalkErrorCode { private String desc; private String solution; - AuthDIngTalkErrorCode(int code, String desc, String solution) { + AuthDingTalkErrorCode(int code, String desc, String solution) { this.code = code; this.desc = desc; this.solution = solution; } - public static AuthDIngTalkErrorCode getErrorCode(int errorCode) { - AuthDIngTalkErrorCode[] errorCodes = AuthDIngTalkErrorCode.values(); - for (AuthDIngTalkErrorCode code : errorCodes) { + public static AuthDingTalkErrorCode getErrorCode(int errorCode) { + AuthDingTalkErrorCode[] errorCodes = AuthDingTalkErrorCode.values(); + for (AuthDingTalkErrorCode code : errorCodes) { if (code.getCode() == errorCode) { return code; } diff --git a/src/main/java/me/zhyd/oauth/model/AuthResponse.java b/src/main/java/me/zhyd/oauth/model/AuthResponse.java index ecce59b..df97699 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthResponse.java +++ b/src/main/java/me/zhyd/oauth/model/AuthResponse.java @@ -2,6 +2,7 @@ package me.zhyd.oauth.model; import lombok.Builder; import lombok.Data; +import me.zhyd.oauth.request.ResponseStatus; /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) @@ -13,7 +14,7 @@ import lombok.Data; @Builder @Data public class AuthResponse { - private int code = 200; - private String msg; + private int code = ResponseStatus.SUCCESS.getCode(); + private String msg = ResponseStatus.SUCCESS.getMsg(); private T data; } diff --git a/src/main/java/me/zhyd/oauth/model/AuthSource.java b/src/main/java/me/zhyd/oauth/model/AuthSource.java index e997ddf..5dac4ab 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/model/AuthSource.java @@ -12,6 +12,8 @@ public enum AuthSource { GITEE, WEIBO, DINGTALK, + BAIDU, QQ, - WEIXIN + WECHAT, + GOOGLE, } diff --git a/src/main/java/me/zhyd/oauth/model/AuthUser.java b/src/main/java/me/zhyd/oauth/model/AuthUser.java index c522dc2..8e9c5f5 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthUser.java +++ b/src/main/java/me/zhyd/oauth/model/AuthUser.java @@ -23,4 +23,5 @@ public class AuthUser { private String remark; private AuthUserGender gender; private AuthSource source; + private String accessToken; } diff --git a/src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java b/src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java new file mode 100644 index 0000000..3975dfb --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java @@ -0,0 +1,63 @@ +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.*; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @website https://www.zhyd.me + * @date 2019/2/19 18:43 + * @since 1.8 + */ +public class AuthBaiduRequest extends BaseAuthRequest { + + public AuthBaiduRequest(AuthConfig config) { + super(config, AuthSource.BAIDU); + } + + @Override + protected String getAccessToken(String code) { + String accessTokenUrl = UrlBuilder.getBaiduAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); + HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); + JSONObject accessTokenObject = JSONObject.parseObject(response.body()); + AuthBaiduErrorCode errorCode = AuthBaiduErrorCode.getErrorCode(accessTokenObject.getString("error")); + if (!AuthBaiduErrorCode.OK.equals(errorCode)) { + throw new AuthException(errorCode.getDesc()); + } + return accessTokenObject.getString("access_token"); + } + + @Override + protected AuthUser getUserInfo(String accessToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.getBaiduUserInfoUrl(accessToken)).execute(); + String userInfo = response.body(); + JSONObject object = JSONObject.parseObject(userInfo); + AuthBaiduErrorCode errorCode = AuthBaiduErrorCode.getErrorCode(object.getString("error")); + if (!AuthBaiduErrorCode.OK.equals(errorCode)) { + throw new AuthException(errorCode.getDesc()); + } + return AuthUser.builder() + .username(object.getString("username")) + .nickname(object.getString("username")) + .gender(AuthUserGender.getRealGender(object.getString("sex"))) + .accessToken(accessToken) + .source(AuthSource.BAIDU) + .build(); + } + + @Override + public AuthResponse revoke(String accessToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.getBaiduRevokeUrl(accessToken)).execute(); + String userInfo = response.body(); + JSONObject object = JSONObject.parseObject(userInfo); + ResponseStatus status = object.getIntValue("result") == 1 ? ResponseStatus.SUCCESS : ResponseStatus.FAILURE; + return AuthResponse.builder().code(status.getCode()).msg(status.getMsg()).build(); + } + +} diff --git a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java index eb197d2..8ba56c3 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java @@ -4,15 +4,14 @@ import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONObject; import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.model.AuthDIngTalkErrorCode; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthDingTalkErrorCode; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthSource; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.utils.DingTalkSignatureUtil; import me.zhyd.oauth.utils.UrlBuilder; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; import java.util.Objects; /** @@ -25,26 +24,11 @@ import java.util.Objects; public class AuthDingTalkRequest extends BaseAuthRequest { public AuthDingTalkRequest(AuthConfig config) { - super(config); + super(config, AuthSource.DINGTALK); } @Override - public void authorize(HttpServletResponse response) { - String authorizeUrl = UrlBuilder.getDingTalkQrConnectUrl(config.getClientId(), config.getRedirectUri()); - try { - response.sendRedirect(authorizeUrl); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public String authorize() { - return UrlBuilder.getDingTalkQrConnectUrl(config.getClientId(), config.getRedirectUri()); - } - - @Override - public AuthResponse login(String code) { + protected AuthUser getUserInfo(String code) { // 根据timestamp, appSecret计算签名值 String stringToSign = System.currentTimeMillis() + ""; String urlEncodeSignature = DingTalkSignatureUtil.computeSignature(config.getClientSecret(), stringToSign); @@ -53,17 +37,21 @@ public class AuthDingTalkRequest extends BaseAuthRequest { .execute(); String userInfo = response.body(); JSONObject object = new JSONObject(userInfo); - AuthDIngTalkErrorCode errorCode = AuthDIngTalkErrorCode.getErrorCode(object.getInt("errcode")); - if (!AuthDIngTalkErrorCode.EC0.equals(errorCode)) { - return AuthResponse.builder().code(errorCode.getCode()).msg(errorCode.getDesc()).build(); + AuthDingTalkErrorCode errorCode = AuthDingTalkErrorCode.getErrorCode(object.getInt("errcode")); + if (!AuthDingTalkErrorCode.EC0.equals(errorCode)) { + throw new AuthException(errorCode.getDesc()); } object = object.getJSONObject("user_info"); - System.out.println(userInfo); + return AuthUser.builder() + .nickname(object.getStr("nick")) + .source(AuthSource.DINGTALK) + .build(); + } + + @Override + public AuthResponse login(String code) { return AuthResponse.builder() - .data(AuthUser.builder() - .nickname(object.getStr("nick")) - .source(AuthSource.DINGTALK) - .build()) + .data(this.getUserInfo(code)) .build(); } } diff --git a/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java b/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java index da4fb5a..98a4a09 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java @@ -4,14 +4,11 @@ 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.model.AuthResponse; +import me.zhyd.oauth.exception.AuthException; import me.zhyd.oauth.model.AuthSource; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.utils.UrlBuilder; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @version 1.0 @@ -22,51 +19,36 @@ import java.io.IOException; public class AuthGiteeRequest extends BaseAuthRequest { public AuthGiteeRequest(AuthConfig config) { - super(config); - } - - @Override - public void authorize(HttpServletResponse response) { - String authorizeUrl = UrlBuilder.getGiteeAuthorizeUrl(config.getClientId(), config.getRedirectUri()); - try { - response.sendRedirect(authorizeUrl); - } catch (IOException e) { - e.printStackTrace(); - } + super(config, AuthSource.GITEE); } @Override - public String authorize() { - return UrlBuilder.getGiteeAuthorizeUrl(config.getClientId(), config.getRedirectUri()); - } - - @Override - public AuthResponse login(String code) { + protected String getAccessToken(String code) { String accessTokenUrl = UrlBuilder.getGiteeAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); JSONObject accessTokenObject = JSONObject.parseObject(response.body()); if (accessTokenObject.containsKey("error")) { - return AuthResponse.builder() - .code(500) - .msg("Unable to get token from gitee using code [" + code + "]") - .build(); + throw new AuthException("Unable to get token from gitee using code [" + code + "]"); } - String accessToken = accessTokenObject.getString("access_token"); - response = HttpRequest.get(UrlBuilder.getGiteeUserInfoUrl(accessToken)).execute(); + return accessTokenObject.getString("access_token"); + } + + @Override + protected AuthUser getUserInfo(String accessToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.getGiteeUserInfoUrl(accessToken)).execute(); String userInfo = response.body(); JSONObject object = JSONObject.parseObject(userInfo); - return AuthResponse.builder() - .data(AuthUser.builder() - .username(object.getString("login")) - .avatar(object.getString("avatar_url")) - .blog(object.getString("blog")) - .nickname(object.getString("name")) - .company(object.getString("company")) - .location(object.getString("address")) - .email(object.getString("email")) - .remark(object.getString("bio")) - .source(AuthSource.GITEE) - .build()) + return AuthUser.builder() + .username(object.getString("login")) + .avatar(object.getString("avatar_url")) + .blog(object.getString("blog")) + .nickname(object.getString("name")) + .company(object.getString("company")) + .location(object.getString("address")) + .email(object.getString("email")) + .remark(object.getString("bio")) + .accessToken(accessToken) + .source(AuthSource.GITEE) .build(); } } diff --git a/src/main/java/me/zhyd/oauth/request/AuthGithubRequest.java b/src/main/java/me/zhyd/oauth/request/AuthGithubRequest.java index 1b8cc49..2c2f096 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthGithubRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthGithubRequest.java @@ -4,16 +4,10 @@ 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.AuthResponse; import me.zhyd.oauth.model.AuthSource; import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.utils.AuthConfigChecker; import me.zhyd.oauth.utils.UrlBuilder; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @version 1.0 @@ -24,45 +18,33 @@ import java.io.IOException; public class AuthGithubRequest extends BaseAuthRequest { public AuthGithubRequest(AuthConfig config) { - super(config); - } - - @Override - public void authorize(HttpServletResponse response) { - String authorizeUrl = UrlBuilder.getGithubAuthorizeUrl(config.getClientId(), config.getRedirectUri()); - try { - response.sendRedirect(authorizeUrl); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public String authorize() { - return UrlBuilder.getGithubAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + super(config, AuthSource.GITHUB); } @Override - public AuthResponse login(String code) { + protected String getAccessToken(String code) { String accessTokenUrl = UrlBuilder.getGithubAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); String accessTokenStr = response.body(); - String accessToken = accessTokenStr.split("&")[0]; - response = HttpRequest.get(UrlBuilder.getGithubUserInfoUrl(accessToken)).execute(); + return accessTokenStr.split("&")[0]; + } + + @Override + protected AuthUser getUserInfo(String accessToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.getGithubUserInfoUrl(accessToken)).execute(); String userInfo = response.body(); JSONObject object = JSONObject.parseObject(userInfo); - return AuthResponse.builder() - .data(AuthUser.builder() - .username(object.getString("login")) - .avatar(object.getString("avatar_url")) - .blog(object.getString("blog")) - .nickname(object.getString("name")) - .company(object.getString("company")) - .location(object.getString("location")) - .email(object.getString("email")) - .remark(object.getString("bio")) - .source(AuthSource.GITHUB) - .build()) + return AuthUser.builder() + .username(object.getString("login")) + .avatar(object.getString("avatar_url")) + .blog(object.getString("blog")) + .nickname(object.getString("name")) + .company(object.getString("company")) + .location(object.getString("location")) + .email(object.getString("email")) + .remark(object.getString("bio")) + .accessToken(accessToken) + .source(AuthSource.GITHUB) .build(); } } diff --git a/src/main/java/me/zhyd/oauth/request/AuthRequest.java b/src/main/java/me/zhyd/oauth/request/AuthRequest.java index 75b6a37..f82948f 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthRequest.java @@ -4,6 +4,7 @@ import me.zhyd.oauth.exception.AuthException; import me.zhyd.oauth.model.AuthResponse; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) @@ -19,7 +20,7 @@ public interface AuthRequest { * * @param response response */ - default void authorize(HttpServletResponse response) { + default void authorize(HttpServletResponse response) throws IOException { throw new AuthException(ResponseStatus.NOT_IMPLEMENTED); } @@ -39,4 +40,13 @@ public interface AuthRequest { default AuthResponse login(String code) { throw new AuthException(ResponseStatus.NOT_IMPLEMENTED); } + + /** + * 撤销授权 + * + * @param accessToken 登录成功后返回的accessToken + */ + default AuthResponse revoke(String accessToken) { + throw new AuthException(ResponseStatus.NOT_IMPLEMENTED); + } } diff --git a/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java b/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java index c49545f..1a20fd1 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java @@ -4,7 +4,7 @@ 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.model.AuthResponse; +import me.zhyd.oauth.exception.AuthException; import me.zhyd.oauth.model.AuthSource; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUserGender; @@ -25,55 +25,41 @@ import java.io.IOException; public class AuthWeiboRequest extends BaseAuthRequest { public AuthWeiboRequest(AuthConfig config) { - super(config); + super(config, AuthSource.WEIBO); } @Override - public void authorize(HttpServletResponse response) { - String authorizeUrl = UrlBuilder.getWeiboAuthorizeUrl(config.getClientId(), config.getRedirectUri()); - try { - response.sendRedirect(authorizeUrl); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public String authorize() { - return UrlBuilder.getWeiboAuthorizeUrl(config.getClientId(), config.getRedirectUri()); - } - - @Override - public AuthResponse login(String code) { + protected String getAccessToken(String code) { String accessTokenUrl = UrlBuilder.getWeiboAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); String accessTokenStr = response.body(); JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); if (accessTokenObject.containsKey("error")) { - return AuthResponse.builder() - .code(500) - .msg("Unable to get token from gitee using code [" + code + "]") - .build(); + throw new AuthException("Unable to get token from gitee using code [" + code + "]"); } String accessToken = accessTokenObject.getString("access_token"); String uid = accessTokenObject.getString("uid"); - response = HttpRequest.get(UrlBuilder.getWeiboUserInfoUrl(uid, accessToken)) + return String.format("uid=%s&access_token=%s", uid, accessToken); + } + + @Override + protected AuthUser getUserInfo(String accessToken) { + HttpResponse response = HttpRequest.get(UrlBuilder.getWeiboUserInfoUrl(accessToken)) .header("Authorization", "OAuth2 " + accessToken) .header("API-RemoteIP", IpUtils.getIp()) .execute(); String userInfo = response.body(); JSONObject object = JSONObject.parseObject(userInfo); - return AuthResponse.builder() - .data(AuthUser.builder() - .username(object.getString("name")) - .avatar(object.getString("profile_image_url")) - .blog(StringUtils.isEmpty(object.getString("url")) ? "https://weibo.com/" + object.getString("profile_url") : object.getString("url")) - .nickname(object.getString("screen_name")) - .location(object.getString("location")) - .remark(object.getString("description")) - .gender(AuthUserGender.getRealGender(object.getString("gender"))) - .source(AuthSource.GITHUB) - .build()) + return AuthUser.builder() + .username(object.getString("name")) + .avatar(object.getString("profile_image_url")) + .blog(StringUtils.isEmpty(object.getString("url")) ? "https://weibo.com/" + object.getString("profile_url") : object.getString("url")) + .nickname(object.getString("screen_name")) + .location(object.getString("location")) + .remark(object.getString("description")) + .gender(AuthUserGender.getRealGender(object.getString("gender"))) + .accessToken(accessToken) + .source(AuthSource.WEIBO) .build(); } } diff --git a/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java b/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java index 2b28c74..aa2c51e 100644 --- a/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java +++ b/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java @@ -3,7 +3,14 @@ package me.zhyd.oauth.request; import lombok.Data; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthSource; +import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.utils.AuthConfigChecker; +import me.zhyd.oauth.utils.UrlBuilder; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * @author yadong.zhang (yadong.zhang0415(a)gmail.com) @@ -15,11 +22,62 @@ import me.zhyd.oauth.utils.AuthConfigChecker; @Data public abstract class BaseAuthRequest implements AuthRequest { protected AuthConfig config; + protected AuthSource source; - public BaseAuthRequest(AuthConfig config) { + public BaseAuthRequest(AuthConfig config, AuthSource source) { this.config = config; + this.source = source; if (!AuthConfigChecker.isSupportedAuth(config)) { throw new AuthException(ResponseStatus.UNSUPPORTED); } } + + protected String getAccessToken(String code) { + return null; + } + + protected abstract AuthUser getUserInfo(String accessToken); + + @Override + public AuthResponse login(String code) { + return AuthResponse.builder() + .data(this.getUserInfo(this.getAccessToken(code))) + .build(); + } + + @Override + public void authorize(HttpServletResponse response) throws IOException { + response.sendRedirect(this.authorize()); + } + + @Override + public String authorize() { + String authorizeUrl = null; + switch (source) { + case WEIBO: + authorizeUrl = UrlBuilder.getWeiboAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + break; + case BAIDU: + authorizeUrl = UrlBuilder.getBaiduAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + break; + case DINGTALK: + authorizeUrl = UrlBuilder.getDingTalkQrConnectUrl(config.getClientId(), config.getRedirectUri()); + break; + case GITEE: + authorizeUrl = UrlBuilder.getGiteeAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + break; + case GITHUB: + authorizeUrl = UrlBuilder.getGithubAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + break; + case QQ: + break; + case WECHAT: + break; + case GOOGLE: + break; + default: + break; + } + return authorizeUrl; + } } diff --git a/src/main/java/me/zhyd/oauth/request/ResponseStatus.java b/src/main/java/me/zhyd/oauth/request/ResponseStatus.java index 570c321..84e169e 100644 --- a/src/main/java/me/zhyd/oauth/request/ResponseStatus.java +++ b/src/main/java/me/zhyd/oauth/request/ResponseStatus.java @@ -8,6 +8,7 @@ package me.zhyd.oauth.request; * @since 1.8 */ public enum ResponseStatus { + SUCCESS(2000, "Success"), FAILURE(5000, "Authentication failure"), NOT_IMPLEMENTED(5001, "Not Implemented"), UNSUPPORTED(5002, "Unsupported authentication, please check the configuration."), diff --git a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java index 5a3b3ae..fbae8c3 100644 --- a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java +++ b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java @@ -20,7 +20,7 @@ public class UrlBuilder { private static final String GITHUB_AUTHORIZE_PATTERN = "{0}?client_id={1}&state=1&redirect_uri={2}"; private static final String WEIBO_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; - private static final String WEIBO_USER_INFO_PATTERN = "{0}?uid={1}&access_token={2}"; + private static final String WEIBO_USER_INFO_PATTERN = "{0}?{1}"; private static final String WEIBO_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}"; private static final String GITEE_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; @@ -30,6 +30,11 @@ public class UrlBuilder { private static final String DING_TALK_QRCONNECT_PATTERN = "{0}?appid={1}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri={2}"; private static final String DING_TALK_USER_INFO_PATTERN = "{0}?signature={1}×tamp={2}&accessKey={3}"; + private static final String BAIDU_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; + private static final String BAIDU_USER_INFO_PATTERN = "{0}?access_token={1}"; + private static final String BAIDU_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&display=popup"; + private static final String BAIDU_REVOKE_PATTERN = "{0}?access_token={1}"; + /** * 获取githubtoken的接口地址 * @@ -80,12 +85,11 @@ public class UrlBuilder { /** * 获取weibo用户详情的接口地址 * - * @param uid 用户id * @param token weibo 应用的token * @return full url */ - public static String getWeiboUserInfoUrl(String uid, String token) { - return MessageFormat.format(WEIBO_USER_INFO_PATTERN, ApiUrlConst.WEIBO_USER_INFO_URL, uid, token); + public static String getWeiboUserInfoUrl(String token) { + return MessageFormat.format(WEIBO_USER_INFO_PATTERN, ApiUrlConst.WEIBO_USER_INFO_URL, token); } /** @@ -155,4 +159,48 @@ public class UrlBuilder { public static String getDingTalkUserInfoUrl(String signature, String timestamp, String accessKey) { return MessageFormat.format(DING_TALK_USER_INFO_PATTERN, ApiUrlConst.DING_TALK_USER_INFO_URL, signature, timestamp, accessKey); } + + /** + * 获取baidu token的接口地址 + * + * @param clientId baidu应用的API Key + * @param clientSecret baidu应用的Secret Key + * @param code baidu授权前的code,用来换token + * @param redirectUri 待跳转的页面 + * @return full url + */ + public static String getBaiduAccessTokenUrl(String clientId, String clientSecret, String code, String redirectUri) { + return MessageFormat.format(BAIDU_ACCESS_TOKEN_PATTERN, ApiUrlConst.BAIDU_ACCESS_TOKEN_URL, clientId, clientSecret, code, redirectUri); + } + + /** + * 获取baidu用户详情的接口地址 + * + * @param token baidu 应用的token + * @return full url + */ + public static String getBaiduUserInfoUrl(String token) { + return MessageFormat.format(BAIDU_USER_INFO_PATTERN, ApiUrlConst.BAIDU_USER_INFO_URL, token); + } + + /** + * 获取baidu授权地址 + * + * @param clientId baidu 应用的API Key + * @param redirectUrl baidu 应用授权成功后的回调地址 + * @return json + */ + public static String getBaiduAuthorizeUrl(String clientId, String redirectUrl) { + return MessageFormat.format(BAIDU_AUTHORIZE_PATTERN, ApiUrlConst.BAIDU_AUTHORIZE_URL, clientId, redirectUrl); + } + + /** + * 获取收回baidu授权的地址 + * + * @param accessToken baidu授权登录后的token + * @return json + */ + public static String getBaiduRevokeUrl(String accessToken) { + return MessageFormat.format(BAIDU_REVOKE_PATTERN, ApiUrlConst.BAIDU_REVOKE_URL, accessToken); + } } -- GitLab