提交 7c2bc828 编写于 作者: 智布道's avatar 智布道 👁

🎨 优化

上级 28b764f0
## v1.1x(未发布)
- 修复抖音登录取值取错层级的问题([issue#I15SIG@Gitee](https://gitee.com/yadong.zhang/JustAuth/issues/I15SIG)
- 升级相关依赖:lombok@v1.18.10,hutool@5.0.5,fastjson@1.2.62,alipay@4.8.10.ALL([PR#11@Gitee](https://gitee.com/yadong.zhang/JustAuth/pulls/11)
- 完善异常提示的逻辑,支持传入Source(平台),发生异常时显示对应的source(平台)
- `checkState`方法从`AuthDefaultRequest`中提出到`AuthChecker`
- `AuthResponseStatus`枚举类中增加`ILLEGAL_STATUS``REQUIRED_REFRESH_TOKEN`两个枚举值
- `AuthSource`接口中增加`getName`方法,用来对外提供实际`source`的字符串值
## v1.13.1
### 2019/11/12
......
......@@ -61,4 +61,16 @@ public interface AuthSource {
default String refresh() {
throw new AuthException(AuthResponseStatus.UNSUPPORTED);
}
/**
* 获取Source的字符串名字
*
* @return name
*/
default String getName() {
if (this instanceof Enum) {
return String.valueOf(this);
}
return this.getClass().getSimpleName();
}
}
......@@ -26,6 +26,8 @@ public enum AuthResponseStatus {
ILLEGAL_REDIRECT_URI(5006, "Illegal redirect uri"),
ILLEGAL_REQUEST(5007, "Illegal request"),
ILLEGAL_CODE(5008, "Illegal code"),
ILLEGAL_STATUS(5009, "Illegal state"),
REQUIRED_REFRESH_TOKEN(5010, "The refresh token is required; it must not be null"),
;
private int code;
......
package me.zhyd.oauth.exception;
import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.enums.AuthResponseStatus;
/**
......@@ -17,6 +18,10 @@ public class AuthException extends RuntimeException {
this(AuthResponseStatus.FAILURE.getCode(), errorMsg);
}
public AuthException(String errorMsg, AuthSource source) {
this(AuthResponseStatus.FAILURE.getCode(), errorMsg, source);
}
public AuthException(int errorCode, String errorMsg) {
super(errorMsg);
this.errorCode = errorCode;
......@@ -24,7 +29,15 @@ public class AuthException extends RuntimeException {
}
public AuthException(AuthResponseStatus status) {
super(status.getMsg());
this(status.getCode(), status.getMsg());
}
public AuthException(int errorCode, String errorMsg, AuthSource source) {
this(errorCode, String.format("%s [%s]", errorMsg, source.getName()));
}
public AuthException(AuthResponseStatus status, AuthSource source) {
this(status.getCode(), status.getMsg(), source);
}
public AuthException(String message, Throwable cause) {
......
......@@ -39,7 +39,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
this.source = source;
this.authStateCache = authStateCache;
if (!AuthChecker.isSupportedAuth(config, source)) {
throw new AuthException(AuthResponseStatus.PARAMETER_INCOMPLETE);
throw new AuthException(AuthResponseStatus.PARAMETER_INCOMPLETE, source);
}
// 校验配置合法性
AuthChecker.checkConfig(config, source);
......@@ -75,7 +75,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
public AuthResponse login(AuthCallback authCallback) {
try {
AuthChecker.checkCode(source, authCallback);
this.checkState(authCallback.getState());
AuthChecker.checkState(authCallback.getState(), source, authStateCache);
AuthToken authToken = this.getAccessToken(authCallback);
AuthUser user = this.getUserInfo(authToken);
......@@ -266,15 +266,4 @@ public abstract class AuthDefaultRequest implements AuthRequest {
return HttpRequest.get(revokeUrl(authToken)).execute();
}
/**
* 校验回调传回的state
*
* @param state {@code state}一定不为空
*/
protected void checkState(String state) {
if (StringUtils.isEmpty(state) || !authStateCache.containsKey(state)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_REQUEST);
}
}
}
......@@ -145,7 +145,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
public AuthResponse refresh(AuthToken oldToken) {
String refreshToken = oldToken.getRefreshToken();
if (StringUtils.isEmpty(refreshToken)) {
throw new AuthException(AuthResponseStatus.UNSUPPORTED);
throw new AuthException(AuthResponseStatus.REQUIRED_REFRESH_TOKEN, source);
}
String refreshTokenUrl = refreshTokenUrl(refreshToken);
return AuthResponse.builder()
......@@ -161,7 +161,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
*/
private void checkResponse(JSONObject object) {
if (object.containsKey("error")) {
throw new AuthException(object.getString("error_description"));
throw new AuthException(object.getString("error_description"), source);
}
}
......
......@@ -57,7 +57,7 @@ public class AuthWeChatEnterpriseRequest extends AuthDefaultRequest {
// 返回 OpenId 或其他,均代表非当前企业用户,不支持
if (!object.containsKey("UserId")) {
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM);
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source);
}
String userId = object.getString("UserId");
HttpResponse userDetailResponse = getUserDetail(authToken.getAccessToken(), userId);
......@@ -88,7 +88,7 @@ public class AuthWeChatEnterpriseRequest extends AuthDefaultRequest {
JSONObject object = JSONObject.parseObject(response.body());
if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
throw new AuthException(object.getString("errmsg"), source);
}
return object;
......
package me.zhyd.oauth.utils;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthDefaultSource;
import me.zhyd.oauth.config.AuthSource;
......@@ -31,7 +32,7 @@ public class AuthChecker {
if (isSupported && AuthDefaultSource.STACK_OVERFLOW == source) {
isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
}
if (isSupported && AuthDefaultSource.WECHAT_ENTERPRISE == source){
if (isSupported && AuthDefaultSource.WECHAT_ENTERPRISE == source) {
isSupported = StringUtils.isNotEmpty(config.getAgentId());
}
return isSupported;
......@@ -47,15 +48,17 @@ public class AuthChecker {
public static void checkConfig(AuthConfig config, AuthSource source) {
String redirectUri = config.getRedirectUri();
if (!GlobalAuthUtil.isHttpProtocol(redirectUri) && !GlobalAuthUtil.isHttpsProtocol(redirectUri)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI);
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
}
// facebook的回调地址必须为https的链接
if (AuthDefaultSource.FACEBOOK == source && !GlobalAuthUtil.isHttpsProtocol(redirectUri)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI);
// Facebook's redirect uri must use the HTTPS protocol
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
}
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1
if (AuthDefaultSource.ALIPAY == source && GlobalAuthUtil.isLocalHost(redirectUri)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI);
// The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
}
}
......@@ -76,7 +79,23 @@ public class AuthChecker {
code = callback.getAuthorization_code();
}
if (StringUtils.isEmpty(code)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE);
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source);
}
}
/**
* 校验回调传回的{@code state},为空或者不存在
* <p>
* {@code state}不存在的情况只有两种:
* 1. {@code state}已使用,被正常清除
* 2. {@code state}为前端伪造,本身就不存在
*
* @param state {@code state}一定不为空
* @param authStateCache {@code authStateCache} state缓存实现
*/
public static void checkState(String state, AuthSource source, AuthStateCache authStateCache) {
if (StringUtils.isEmpty(state) || !authStateCache.containsKey(state)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_STATUS, source);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册