提交 368cd046 编写于 作者: 智布道's avatar 智布道 👁

👽 重构AuthRequest的实现方式、加入百度授权登录

上级 3777027d
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
<td align="center" width="200"><a href="https://gitee.com/"><img src="https://gitee.com/logo_icon.png" width="30"></a></td> <td align="center" width="200"><a href="https://gitee.com/"><img src="https://gitee.com/logo_icon.png" width="30"></a></td>
<td align="center" width="200"><a href="https://github.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/github.png" width="30"></a></td> <td align="center" width="200"><a href="https://github.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/github.png" width="30"></a></td>
<td align="center" width="200"><a href="https://weibo.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/weibo.png" width="30"></a></td> <td align="center" width="200"><a href="https://weibo.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/weibo.png" width="30"></a></td>
<td align="center" width="200"><a href="https://www.csdn.net/"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="30"></a></td>
<td align="center" width="200"><a href="https://www.dingtalk.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/dingding.png" width="30"></a></td> <td align="center" width="200"><a href="https://www.dingtalk.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/dingding.png" width="30"></a></td>
<td align="center" width="200"><a href="https://www.dingtalk.com"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/baidu.png" width="30"></a></td>
<td align="center" width="200"><a href="https://www.csdn.net/"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="30"></a></td>
<td align="center" width="200"><a href="https://connect.qq.com/devuser.html#/"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/qq.png" width="30"></a></td> <td align="center" width="200"><a href="https://connect.qq.com/devuser.html#/"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/qq.png" width="30"></a></td>
<td align="center" width="200"><a href="https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechats.png" width="30"></a></td> <td align="center" width="200"><a href="https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechats.png" width="30"></a></td>
</tr> </tr>
...@@ -34,8 +35,9 @@ ...@@ -34,8 +35,9 @@
<td align="center" width="200"><a href="#Gitee">Gitee</a></td> <td align="center" width="200"><a href="#Gitee">Gitee</a></td>
<td align="center" width="200"><a href="#Github">Github</a></td> <td align="center" width="200"><a href="#Github">Github</a></td>
<td align="center" width="200"><a href="#Weibo">Weibo</a></td> <td align="center" width="200"><a href="#Weibo">Weibo</a></td>
<td align="center" width="200"><a href="#CSDN">CSDN</a></td>
<td align="center" width="200"><a href="#钉钉">钉钉</a></td> <td align="center" width="200"><a href="#钉钉">钉钉</a></td>
<td align="center" width="200"><a href="#百度">百度</a></td>
<td align="center" width="200"><a href="#CSDN">CSDN</a></td>
<td align="center" width="200"><a href="#QQ">QQ</a></td> <td align="center" width="200"><a href="#QQ">QQ</a></td>
<td align="center" width="200"><a href="#微信">微信</a></td> <td align="center" width="200"><a href="#微信">微信</a></td>
</tr> </tr>
...@@ -75,10 +77,41 @@ authRequest.login("code"); ...@@ -75,10 +77,41 @@ authRequest.login("code");
#### API列表 #### API列表
| :computer: 平台 | :coffee: API类 | :page_facing_up: SDK | | :computer: 平台 | :coffee: API类 | :page_facing_up: SDK |
|:------:|:-------:|:-------:| |:------:|:-------:|:-------:|
| <img src="https://gitee.com/logo_icon.png" width="20"> | [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) | | <img src="https://gitee.com/logo_icon.png" width="20"> | [AuthGiteeRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [参考文档](https://github.com/settings/developers) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/github.png" width="20"> | [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) | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/github.png" width="20"> | [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) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/weibo.png" width="20"> | [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) | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/weibo.png" width="20"> | [AuthWeiboRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | [参考文档](https://open.weibo.com/apps) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="20"> | AuthCsdnRequest | [https://connect.qq.com/](https://connect.qq.com/) | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/dingding.png" width="20"> | [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) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/dingding.png" width="20"> | [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) | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/baidu.png" width="20"> | [AuthBaiduRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthBaiduRequest.java) | [参考文档](https://developer.baidu.com/) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="20"> | AuthCsdnRequest | [参考文档](https://connect.qq.com/) |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/qq.png" width="20"> | AuthQqRequest | 待续 | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/qq.png" width="20"> | AuthQqRequest | 待续 |
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechats.png" width="20"> | AuthWechatRequest | 待续 | | <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechats.png" width="20"> | AuthWechatRequest | 待续 |
### 参考图例
##### Gitee
待续
##### Github
待续
##### Weibo
待续
##### 钉钉
待续
##### 百度
待续
##### CSDN
待续
##### 微信
待续
...@@ -66,4 +66,24 @@ public class ApiUrlConst { ...@@ -66,4 +66,24 @@ public class ApiUrlConst {
*/ */
public static final String DING_TALK_USER_INFO_URL = "https://oapi.dingtalk.com/sns/getuserinfo_bycode"; 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";
} }
...@@ -10,12 +10,18 @@ import me.zhyd.oauth.request.ResponseStatus; ...@@ -10,12 +10,18 @@ import me.zhyd.oauth.request.ResponseStatus;
* @since 1.8 * @since 1.8
*/ */
public class AuthException extends RuntimeException { 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) { public AuthException(int errorCode, String errorMsg) {
super(message); super(errorCode + ":" + errorMsg);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
} }
public AuthException(ResponseStatus status) { public AuthException(ResponseStatus status) {
...@@ -26,11 +32,11 @@ public class AuthException extends RuntimeException { ...@@ -26,11 +32,11 @@ public class AuthException extends RuntimeException {
super(message, cause); super(message, cause);
} }
public AuthException(Throwable cause) { public int getErrorCode() {
super(cause); return errorCode;
} }
protected AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { public String getErrorMsg() {
super(message, cause, enableSuppression, writableStackTrace); return errorMsg;
} }
} }
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;
}
}
...@@ -7,7 +7,7 @@ package me.zhyd.oauth.model; ...@@ -7,7 +7,7 @@ package me.zhyd.oauth.model;
* @date 2019/2/19 9:42 * @date 2019/2/19 9:42
* @since 1.8 * @since 1.8
*/ */
public enum AuthDIngTalkErrorCode { public enum AuthDingTalkErrorCode {
/** /**
* 异常状态码 * 异常状态码
*/ */
...@@ -377,15 +377,15 @@ public enum AuthDIngTalkErrorCode { ...@@ -377,15 +377,15 @@ public enum AuthDIngTalkErrorCode {
private String desc; private String desc;
private String solution; private String solution;
AuthDIngTalkErrorCode(int code, String desc, String solution) { AuthDingTalkErrorCode(int code, String desc, String solution) {
this.code = code; this.code = code;
this.desc = desc; this.desc = desc;
this.solution = solution; this.solution = solution;
} }
public static AuthDIngTalkErrorCode getErrorCode(int errorCode) { public static AuthDingTalkErrorCode getErrorCode(int errorCode) {
AuthDIngTalkErrorCode[] errorCodes = AuthDIngTalkErrorCode.values(); AuthDingTalkErrorCode[] errorCodes = AuthDingTalkErrorCode.values();
for (AuthDIngTalkErrorCode code : errorCodes) { for (AuthDingTalkErrorCode code : errorCodes) {
if (code.getCode() == errorCode) { if (code.getCode() == errorCode) {
return code; return code;
} }
......
...@@ -2,6 +2,7 @@ package me.zhyd.oauth.model; ...@@ -2,6 +2,7 @@ package me.zhyd.oauth.model;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import me.zhyd.oauth.request.ResponseStatus;
/** /**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
...@@ -13,7 +14,7 @@ import lombok.Data; ...@@ -13,7 +14,7 @@ import lombok.Data;
@Builder @Builder
@Data @Data
public class AuthResponse<T> { public class AuthResponse<T> {
private int code = 200; private int code = ResponseStatus.SUCCESS.getCode();
private String msg; private String msg = ResponseStatus.SUCCESS.getMsg();
private T data; private T data;
} }
...@@ -12,6 +12,8 @@ public enum AuthSource { ...@@ -12,6 +12,8 @@ public enum AuthSource {
GITEE, GITEE,
WEIBO, WEIBO,
DINGTALK, DINGTALK,
BAIDU,
QQ, QQ,
WEIXIN WECHAT,
GOOGLE,
} }
...@@ -23,4 +23,5 @@ public class AuthUser { ...@@ -23,4 +23,5 @@ public class AuthUser {
private String remark; private String remark;
private AuthUserGender gender; private AuthUserGender gender;
private AuthSource source; private AuthSource source;
private String accessToken;
} }
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();
}
}
...@@ -4,15 +4,14 @@ import cn.hutool.http.HttpRequest; ...@@ -4,15 +4,14 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import me.zhyd.oauth.config.AuthConfig; 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.AuthResponse;
import me.zhyd.oauth.model.AuthSource; import me.zhyd.oauth.model.AuthSource;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.utils.DingTalkSignatureUtil; import me.zhyd.oauth.utils.DingTalkSignatureUtil;
import me.zhyd.oauth.utils.UrlBuilder; import me.zhyd.oauth.utils.UrlBuilder;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects; import java.util.Objects;
/** /**
...@@ -25,26 +24,11 @@ import java.util.Objects; ...@@ -25,26 +24,11 @@ import java.util.Objects;
public class AuthDingTalkRequest extends BaseAuthRequest { public class AuthDingTalkRequest extends BaseAuthRequest {
public AuthDingTalkRequest(AuthConfig config) { public AuthDingTalkRequest(AuthConfig config) {
super(config); super(config, AuthSource.DINGTALK);
} }
@Override @Override
public void authorize(HttpServletResponse response) { protected AuthUser getUserInfo(String code) {
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) {
// 根据timestamp, appSecret计算签名值 // 根据timestamp, appSecret计算签名值
String stringToSign = System.currentTimeMillis() + ""; String stringToSign = System.currentTimeMillis() + "";
String urlEncodeSignature = DingTalkSignatureUtil.computeSignature(config.getClientSecret(), stringToSign); String urlEncodeSignature = DingTalkSignatureUtil.computeSignature(config.getClientSecret(), stringToSign);
...@@ -53,17 +37,21 @@ public class AuthDingTalkRequest extends BaseAuthRequest { ...@@ -53,17 +37,21 @@ public class AuthDingTalkRequest extends BaseAuthRequest {
.execute(); .execute();
String userInfo = response.body(); String userInfo = response.body();
JSONObject object = new JSONObject(userInfo); JSONObject object = new JSONObject(userInfo);
AuthDIngTalkErrorCode errorCode = AuthDIngTalkErrorCode.getErrorCode(object.getInt("errcode")); AuthDingTalkErrorCode errorCode = AuthDingTalkErrorCode.getErrorCode(object.getInt("errcode"));
if (!AuthDIngTalkErrorCode.EC0.equals(errorCode)) { if (!AuthDingTalkErrorCode.EC0.equals(errorCode)) {
return AuthResponse.builder().code(errorCode.getCode()).msg(errorCode.getDesc()).build(); throw new AuthException(errorCode.getDesc());
} }
object = object.getJSONObject("user_info"); 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() return AuthResponse.builder()
.data(AuthUser.builder() .data(this.getUserInfo(code))
.nickname(object.getStr("nick"))
.source(AuthSource.DINGTALK)
.build())
.build(); .build();
} }
} }
...@@ -4,14 +4,11 @@ import cn.hutool.http.HttpRequest; ...@@ -4,14 +4,11 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import me.zhyd.oauth.config.AuthConfig; 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.AuthSource;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.utils.UrlBuilder; import me.zhyd.oauth.utils.UrlBuilder;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 1.0 * @version 1.0
...@@ -22,51 +19,36 @@ import java.io.IOException; ...@@ -22,51 +19,36 @@ import java.io.IOException;
public class AuthGiteeRequest extends BaseAuthRequest { public class AuthGiteeRequest extends BaseAuthRequest {
public AuthGiteeRequest(AuthConfig config) { public AuthGiteeRequest(AuthConfig config) {
super(config); super(config, AuthSource.GITEE);
}
@Override
public void authorize(HttpServletResponse response) {
String authorizeUrl = UrlBuilder.getGiteeAuthorizeUrl(config.getClientId(), config.getRedirectUri());
try {
response.sendRedirect(authorizeUrl);
} catch (IOException e) {
e.printStackTrace();
}
} }
@Override @Override
public String authorize() { protected String getAccessToken(String code) {
return UrlBuilder.getGiteeAuthorizeUrl(config.getClientId(), config.getRedirectUri());
}
@Override
public AuthResponse login(String code) {
String accessTokenUrl = UrlBuilder.getGiteeAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); String accessTokenUrl = UrlBuilder.getGiteeAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri());
HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); HttpResponse response = HttpRequest.post(accessTokenUrl).execute();
JSONObject accessTokenObject = JSONObject.parseObject(response.body()); JSONObject accessTokenObject = JSONObject.parseObject(response.body());
if (accessTokenObject.containsKey("error")) { if (accessTokenObject.containsKey("error")) {
return AuthResponse.builder() throw new AuthException("Unable to get token from gitee using code [" + code + "]");
.code(500)
.msg("Unable to get token from gitee using code [" + code + "]")
.build();
} }
String accessToken = accessTokenObject.getString("access_token"); return accessTokenObject.getString("access_token");
response = HttpRequest.get(UrlBuilder.getGiteeUserInfoUrl(accessToken)).execute(); }
@Override
protected AuthUser getUserInfo(String accessToken) {
HttpResponse response = HttpRequest.get(UrlBuilder.getGiteeUserInfoUrl(accessToken)).execute();
String userInfo = response.body(); String userInfo = response.body();
JSONObject object = JSONObject.parseObject(userInfo); JSONObject object = JSONObject.parseObject(userInfo);
return AuthResponse.builder() return AuthUser.builder()
.data(AuthUser.builder() .username(object.getString("login"))
.username(object.getString("login")) .avatar(object.getString("avatar_url"))
.avatar(object.getString("avatar_url")) .blog(object.getString("blog"))
.blog(object.getString("blog")) .nickname(object.getString("name"))
.nickname(object.getString("name")) .company(object.getString("company"))
.company(object.getString("company")) .location(object.getString("address"))
.location(object.getString("address")) .email(object.getString("email"))
.email(object.getString("email")) .remark(object.getString("bio"))
.remark(object.getString("bio")) .accessToken(accessToken)
.source(AuthSource.GITEE) .source(AuthSource.GITEE)
.build())
.build(); .build();
} }
} }
...@@ -4,16 +4,10 @@ import cn.hutool.http.HttpRequest; ...@@ -4,16 +4,10 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import me.zhyd.oauth.config.AuthConfig; 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.AuthSource;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.utils.AuthConfigChecker;
import me.zhyd.oauth.utils.UrlBuilder; import me.zhyd.oauth.utils.UrlBuilder;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 1.0 * @version 1.0
...@@ -24,45 +18,33 @@ import java.io.IOException; ...@@ -24,45 +18,33 @@ import java.io.IOException;
public class AuthGithubRequest extends BaseAuthRequest { public class AuthGithubRequest extends BaseAuthRequest {
public AuthGithubRequest(AuthConfig config) { public AuthGithubRequest(AuthConfig config) {
super(config); super(config, AuthSource.GITHUB);
}
@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());
} }
@Override @Override
public AuthResponse login(String code) { protected String getAccessToken(String code) {
String accessTokenUrl = UrlBuilder.getGithubAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); String accessTokenUrl = UrlBuilder.getGithubAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri());
HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); HttpResponse response = HttpRequest.post(accessTokenUrl).execute();
String accessTokenStr = response.body(); String accessTokenStr = response.body();
String accessToken = accessTokenStr.split("&")[0]; return accessTokenStr.split("&")[0];
response = HttpRequest.get(UrlBuilder.getGithubUserInfoUrl(accessToken)).execute(); }
@Override
protected AuthUser getUserInfo(String accessToken) {
HttpResponse response = HttpRequest.get(UrlBuilder.getGithubUserInfoUrl(accessToken)).execute();
String userInfo = response.body(); String userInfo = response.body();
JSONObject object = JSONObject.parseObject(userInfo); JSONObject object = JSONObject.parseObject(userInfo);
return AuthResponse.builder() return AuthUser.builder()
.data(AuthUser.builder() .username(object.getString("login"))
.username(object.getString("login")) .avatar(object.getString("avatar_url"))
.avatar(object.getString("avatar_url")) .blog(object.getString("blog"))
.blog(object.getString("blog")) .nickname(object.getString("name"))
.nickname(object.getString("name")) .company(object.getString("company"))
.company(object.getString("company")) .location(object.getString("location"))
.location(object.getString("location")) .email(object.getString("email"))
.email(object.getString("email")) .remark(object.getString("bio"))
.remark(object.getString("bio")) .accessToken(accessToken)
.source(AuthSource.GITHUB) .source(AuthSource.GITHUB)
.build())
.build(); .build();
} }
} }
...@@ -4,6 +4,7 @@ import me.zhyd.oauth.exception.AuthException; ...@@ -4,6 +4,7 @@ import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthResponse;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
...@@ -19,7 +20,7 @@ public interface AuthRequest { ...@@ -19,7 +20,7 @@ public interface AuthRequest {
* *
* @param response response * @param response response
*/ */
default void authorize(HttpServletResponse response) { default void authorize(HttpServletResponse response) throws IOException {
throw new AuthException(ResponseStatus.NOT_IMPLEMENTED); throw new AuthException(ResponseStatus.NOT_IMPLEMENTED);
} }
...@@ -39,4 +40,13 @@ public interface AuthRequest { ...@@ -39,4 +40,13 @@ public interface AuthRequest {
default AuthResponse login(String code) { default AuthResponse login(String code) {
throw new AuthException(ResponseStatus.NOT_IMPLEMENTED); throw new AuthException(ResponseStatus.NOT_IMPLEMENTED);
} }
/**
* 撤销授权
*
* @param accessToken 登录成功后返回的accessToken
*/
default AuthResponse revoke(String accessToken) {
throw new AuthException(ResponseStatus.NOT_IMPLEMENTED);
}
} }
...@@ -4,7 +4,7 @@ import cn.hutool.http.HttpRequest; ...@@ -4,7 +4,7 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import me.zhyd.oauth.config.AuthConfig; 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.AuthSource;
import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.model.AuthUserGender; import me.zhyd.oauth.model.AuthUserGender;
...@@ -25,55 +25,41 @@ import java.io.IOException; ...@@ -25,55 +25,41 @@ import java.io.IOException;
public class AuthWeiboRequest extends BaseAuthRequest { public class AuthWeiboRequest extends BaseAuthRequest {
public AuthWeiboRequest(AuthConfig config) { public AuthWeiboRequest(AuthConfig config) {
super(config); super(config, AuthSource.WEIBO);
} }
@Override @Override
public void authorize(HttpServletResponse response) { protected String getAccessToken(String code) {
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) {
String accessTokenUrl = UrlBuilder.getWeiboAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri()); String accessTokenUrl = UrlBuilder.getWeiboAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config.getRedirectUri());
HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); HttpResponse response = HttpRequest.post(accessTokenUrl).execute();
String accessTokenStr = response.body(); String accessTokenStr = response.body();
JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr);
if (accessTokenObject.containsKey("error")) { if (accessTokenObject.containsKey("error")) {
return AuthResponse.builder() throw new AuthException("Unable to get token from gitee using code [" + code + "]");
.code(500)
.msg("Unable to get token from gitee using code [" + code + "]")
.build();
} }
String accessToken = accessTokenObject.getString("access_token"); String accessToken = accessTokenObject.getString("access_token");
String uid = accessTokenObject.getString("uid"); 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("Authorization", "OAuth2 " + accessToken)
.header("API-RemoteIP", IpUtils.getIp()) .header("API-RemoteIP", IpUtils.getIp())
.execute(); .execute();
String userInfo = response.body(); String userInfo = response.body();
JSONObject object = JSONObject.parseObject(userInfo); JSONObject object = JSONObject.parseObject(userInfo);
return AuthResponse.builder() return AuthUser.builder()
.data(AuthUser.builder() .username(object.getString("name"))
.username(object.getString("name")) .avatar(object.getString("profile_image_url"))
.avatar(object.getString("profile_image_url")) .blog(StringUtils.isEmpty(object.getString("url")) ? "https://weibo.com/" + object.getString("profile_url") : object.getString("url"))
.blog(StringUtils.isEmpty(object.getString("url")) ? "https://weibo.com/" + object.getString("profile_url") : object.getString("url")) .nickname(object.getString("screen_name"))
.nickname(object.getString("screen_name")) .location(object.getString("location"))
.location(object.getString("location")) .remark(object.getString("description"))
.remark(object.getString("description")) .gender(AuthUserGender.getRealGender(object.getString("gender")))
.gender(AuthUserGender.getRealGender(object.getString("gender"))) .accessToken(accessToken)
.source(AuthSource.GITHUB) .source(AuthSource.WEIBO)
.build())
.build(); .build();
} }
} }
...@@ -3,7 +3,14 @@ package me.zhyd.oauth.request; ...@@ -3,7 +3,14 @@ package me.zhyd.oauth.request;
import lombok.Data; import lombok.Data;
import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException; 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.AuthConfigChecker;
import me.zhyd.oauth.utils.UrlBuilder;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
...@@ -15,11 +22,62 @@ import me.zhyd.oauth.utils.AuthConfigChecker; ...@@ -15,11 +22,62 @@ import me.zhyd.oauth.utils.AuthConfigChecker;
@Data @Data
public abstract class BaseAuthRequest implements AuthRequest { public abstract class BaseAuthRequest implements AuthRequest {
protected AuthConfig config; protected AuthConfig config;
protected AuthSource source;
public BaseAuthRequest(AuthConfig config) { public BaseAuthRequest(AuthConfig config, AuthSource source) {
this.config = config; this.config = config;
this.source = source;
if (!AuthConfigChecker.isSupportedAuth(config)) { if (!AuthConfigChecker.isSupportedAuth(config)) {
throw new AuthException(ResponseStatus.UNSUPPORTED); 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;
}
} }
...@@ -8,6 +8,7 @@ package me.zhyd.oauth.request; ...@@ -8,6 +8,7 @@ package me.zhyd.oauth.request;
* @since 1.8 * @since 1.8
*/ */
public enum ResponseStatus { public enum ResponseStatus {
SUCCESS(2000, "Success"),
FAILURE(5000, "Authentication failure"), FAILURE(5000, "Authentication failure"),
NOT_IMPLEMENTED(5001, "Not Implemented"), NOT_IMPLEMENTED(5001, "Not Implemented"),
UNSUPPORTED(5002, "Unsupported authentication, please check the configuration."), UNSUPPORTED(5002, "Unsupported authentication, please check the configuration."),
......
...@@ -20,7 +20,7 @@ public class UrlBuilder { ...@@ -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 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_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 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}"; 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 { ...@@ -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_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}&timestamp={2}&accessKey={3}"; private static final String DING_TALK_USER_INFO_PATTERN = "{0}?signature={1}&timestamp={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的接口地址 * 获取githubtoken的接口地址
* *
...@@ -80,12 +85,11 @@ public class UrlBuilder { ...@@ -80,12 +85,11 @@ public class UrlBuilder {
/** /**
* 获取weibo用户详情的接口地址 * 获取weibo用户详情的接口地址
* *
* @param uid 用户id
* @param token weibo 应用的token * @param token weibo 应用的token
* @return full url * @return full url
*/ */
public static String getWeiboUserInfoUrl(String uid, String token) { public static String getWeiboUserInfoUrl(String token) {
return MessageFormat.format(WEIBO_USER_INFO_PATTERN, ApiUrlConst.WEIBO_USER_INFO_URL, uid, token); return MessageFormat.format(WEIBO_USER_INFO_PATTERN, ApiUrlConst.WEIBO_USER_INFO_URL, token);
} }
/** /**
...@@ -155,4 +159,48 @@ public class UrlBuilder { ...@@ -155,4 +159,48 @@ public class UrlBuilder {
public static String getDingTalkUserInfoUrl(String signature, String timestamp, String accessKey) { 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); 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);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册