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

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

上级 3777027d
......@@ -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://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://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/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://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>
......@@ -34,8 +35,9 @@
<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="#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="#CSDN">CSDN</a></td>
<td align="center" width="200"><a href="#QQ">QQ</a></td>
<td align="center" width="200"><a href="#微信">微信</a></td>
</tr>
......@@ -75,10 +77,41 @@ authRequest.login("code");
#### API列表
| :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/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/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/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](https://open-doc.dingtalk.com/microapp/serverapi2/kymkv6) |
| <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) |
| <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/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/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/wechats.png" width="20"> | AuthWechatRequest | 待续 |
### 参考图例
##### Gitee
待续
##### Github
待续
##### Weibo
待续
##### 钉钉
待续
##### 百度
待续
##### CSDN
待续
##### 微信
待续
......@@ -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";
}
......@@ -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;
}
}
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;
* @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;
}
......
......@@ -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<T> {
private int code = 200;
private String msg;
private int code = ResponseStatus.SUCCESS.getCode();
private String msg = ResponseStatus.SUCCESS.getMsg();
private T data;
}
......@@ -12,6 +12,8 @@ public enum AuthSource {
GITEE,
WEIBO,
DINGTALK,
BAIDU,
QQ,
WEIXIN
WECHAT,
GOOGLE,
}
......@@ -23,4 +23,5 @@ public class AuthUser {
private String remark;
private AuthUserGender gender;
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;
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();
}
}
......@@ -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();
}
}
......@@ -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();
}
}
......@@ -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);
}
}
......@@ -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();
}
}
......@@ -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;
}
}
......@@ -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."),
......
......@@ -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}&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的接口地址
*
......@@ -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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册