diff --git a/CHANGELOGS.md b/CHANGELOGS.md
index 7747f1095a4147211877c053b165268798c68895..f0d52765122c1dd58909d13356d31fd689c65133 100644
--- a/CHANGELOGS.md
+++ b/CHANGELOGS.md
@@ -1,3 +1,14 @@
+## 1.16.3
+
+### 2021/8/**
+
+- 发布 v1.16.3
+- PR
+ - 合并 Gitee PR ([#27](https://gitee.com/yadong.zhang/JustAuth/pulls/27))
+- 修改
+ 在 Gitee PR ([#27](https://gitee.com/yadong.zhang/JustAuth/pulls/27)) 的基础上重构代码,增加 Builder 方式创建 AuthRequest
+
+
## 1.16.2
### 2021/7/28
diff --git a/README.md b/README.md
index 5c86ac4ad6e190a90d799c5acadfad3d9eb116f9..b558ccf41bab9f89293b647cb45ac9c7917362b4 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、
## 快速开始
-- 引入依赖
+### 引入依赖
```xml
me.zhyd.oauth
@@ -69,22 +69,8 @@ JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、
1.16.2
```
-- 调用api
-```java
-// 创建授权request
-AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
- .clientId("clientId")
- .clientSecret("clientSecret")
- .redirectUri("redirectUri")
- .build());
-// 生成授权页面
-authRequest.authorize("state");
-// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的参数
-// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
-authRequest.login(callback);
-```
-如下**任选一种** HTTP 工具 依赖,_项目内如果已有,请忽略。另外需要特别注意,如果项目中已经引入了低版本的依赖,请先排除低版本以后来,引入高版本或者最新版本的依赖_
+如下**任选一种** HTTP 工具 依赖,_项目内如果已有,请忽略。另外需要特别注意,如果项目中已经引入了低版本的依赖,请先排除低版本依赖后,引入高版本或者最新版本的依赖_
- hutool-http
@@ -92,7 +78,7 @@ authRequest.login(callback);
cn.hutool
hutool-http
- 5.2.5
+ 5.7.7
```
@@ -102,7 +88,7 @@ authRequest.login(callback);
org.apache.httpcomponents
httpclient
- 4.5.12
+ 4.5.13
```
@@ -112,9 +98,78 @@ authRequest.login(callback);
com.squareup.okhttp3
okhttp
- 4.4.1
+ 4.9.1
```
+
+### 调用api
+
+#### 普通方式
+
+```java
+// 创建授权request
+AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
+ .clientId("clientId")
+ .clientSecret("clientSecret")
+ .redirectUri("redirectUri")
+ .build());
+// 生成授权页面
+authRequest.authorize("state");
+// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的参数
+// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
+authRequest.login(callback);
+```
+
+#### Builder 方式一
+
+静态配置 `AuthConfig`
+
+```java
+AuthRequest authRequest = AuthRequestBuilder.builder()
+ .source("github")
+ .authConfig(AuthConfig.builder()
+ .clientId("clientId")
+ .clientSecret("clientSecret")
+ .redirectUri("redirectUri")
+ .build())
+ .build();
+// 生成授权页面
+ authRequest.authorize("state");
+// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的参数
+// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
+ authRequest.login(callback);
+```
+
+#### Builder 方式二
+
+静态获取并配置 `AuthConfig`
+
+```java
+AuthRequest authRequest = AuthRequestBuilder.builder()
+ .source("gitee")
+ .authConfig((source) -> {
+ // 通过 source 动态获取 AuthConfig
+ // 此处可以灵活的从 sql 中取配置也可以从配置文件中取配置
+ return AuthConfig.builder()
+ .clientId("clientId")
+ .clientSecret("clientSecret")
+ .redirectUri("redirectUri")
+ .build();
+ })
+ .build();
+Assert.assertTrue(authRequest instanceof AuthGiteeRequest);
+System.out.println(authRequest.authorize(AuthStateUtils.createState()));
+```
+
+#### Builder 方式支持自定义的平台
+
+```java
+AuthRequest authRequest = AuthRequestBuilder.builder()
+ // 关键点:将自定义实现的 AuthSource 配置上
+ .extendSource(AuthExtendSource.values())
+ // ... 其他内容不变,参考上面的示例
+ .build();
+```
## 赞助和支持
diff --git a/src/main/java/me/zhyd/oauth/AuthRequestBuilder.java b/src/main/java/me/zhyd/oauth/AuthRequestBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bf86fa60152416208aeb9220360c09f413f6786
--- /dev/null
+++ b/src/main/java/me/zhyd/oauth/AuthRequestBuilder.java
@@ -0,0 +1,98 @@
+package me.zhyd.oauth;
+
+import me.zhyd.oauth.cache.AuthStateCache;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.config.AuthDefaultSource;
+import me.zhyd.oauth.config.AuthSource;
+import me.zhyd.oauth.exception.AuthException;
+import me.zhyd.oauth.request.AuthDefaultRequest;
+import me.zhyd.oauth.request.AuthRequest;
+import me.zhyd.oauth.utils.StringUtils;
+
+import java.util.Arrays;
+import java.util.function.Function;
+
+/**
+ * 快捷的构建 AuthRequest
+ *
+ * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
+ * @version 1.0.0
+ * @since 1.16.3
+ */
+public class AuthRequestBuilder {
+ private String source;
+ private AuthConfig authConfig;
+ private AuthStateCache authStateCache;
+ private AuthSource[] extendSource;
+
+ private AuthRequestBuilder() {
+
+ }
+
+ public static AuthRequestBuilder builder() {
+ return new AuthRequestBuilder();
+ }
+
+ public AuthRequestBuilder source(String source) {
+ this.source = source;
+ return this;
+ }
+
+ public AuthRequestBuilder authConfig(AuthConfig authConfig) {
+ this.authConfig = authConfig;
+ return this;
+ }
+
+ public AuthRequestBuilder authConfig(Function authConfig) {
+ this.authConfig = authConfig.apply(this.source);
+ return this;
+ }
+
+ public AuthRequestBuilder authStateCache(AuthStateCache authStateCache) {
+ this.authStateCache = authStateCache;
+ return this;
+ }
+
+ public AuthRequestBuilder extendSource(AuthSource... extendSource) {
+ this.extendSource = extendSource;
+ return this;
+ }
+
+ public AuthRequest build() {
+ if (StringUtils.isEmpty(this.source)) {
+ throw new AuthException("未配置 source");
+ }
+ if (null == this.authConfig) {
+ throw new AuthException("未配置 AuthConfig");
+ }
+ // 合并 JustAuth 默认的 AuthDefaultSource 和 开发者自定义的 AuthSource
+ AuthSource[] sources = this.concat(AuthDefaultSource.values(), extendSource);
+ // 筛选符合条件的 AuthSource
+ AuthSource source = Arrays.stream(sources).distinct()
+ .filter(authSource -> authSource.getName().equalsIgnoreCase(this.source))
+ .findAny()
+ .orElseThrow(() -> new AuthException("未获取到有效的 AuthSource 配置"));
+ Class extends AuthDefaultRequest> targetClass = source.getTargetClass();
+ try {
+ if (this.authStateCache == null) {
+ return targetClass.getDeclaredConstructor(AuthConfig.class).newInstance(this.authConfig);
+ } else {
+ return targetClass.getDeclaredConstructor(AuthConfig.class, AuthStateCache.class).newInstance(this.authConfig, this.authStateCache);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new AuthException("未获取到有效的 Auth 配置");
+ }
+ }
+
+ private AuthSource[] concat(AuthSource[] first, AuthSource[] second) {
+ if (null == second || second.length == 0) {
+ return first;
+ }
+ AuthSource[] result = new AuthSource[first.length + second.length];
+ System.arraycopy(first, 0, result, 0, first.length);
+ System.arraycopy(second, 0, result, first.length, second.length);
+ return result;
+ }
+
+}
diff --git a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
index fb750ac345904914335ddcd607ab0af1e97d2ccb..0711e268f4929b818055167bd1005a52273e6c84 100644
--- a/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
+++ b/src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
@@ -1,12 +1,9 @@
package me.zhyd.oauth.config;
-import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.enums.AuthResponseStatus;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.request.*;
-import java.util.Arrays;
-
/**
* JustAuth内置的各api需要的url, 用枚举类分平台类型管理
*
@@ -17,7 +14,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Github
*/
- GITHUB(AuthGithubRequest.class) {
+ GITHUB {
@Override
public String authorize() {
return "https://github.com/login/oauth/authorize";
@@ -32,11 +29,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.github.com/user";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthGithubRequest.class;
+ }
},
/**
* 新浪微博
*/
- WEIBO(AuthWeiboRequest.class) {
+ WEIBO {
@Override
public String authorize() {
return "https://api.weibo.com/oauth2/authorize";
@@ -56,11 +58,16 @@ public enum AuthDefaultSource implements AuthSource {
public String revoke() {
return "https://api.weibo.com/oauth2/revokeoauth2";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthWeiboRequest.class;
+ }
},
/**
* gitee
*/
- GITEE(AuthGiteeRequest.class) {
+ GITEE {
@Override
public String authorize() {
return "https://gitee.com/oauth/authorize";
@@ -75,11 +82,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://gitee.com/api/v5/user";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthGiteeRequest.class;
+ }
},
/**
* 钉钉扫码登录
*/
- DINGTALK(AuthDingTalkRequest.class) {
+ DINGTALK {
@Override
public String authorize() {
return "https://oapi.dingtalk.com/connect/qrconnect";
@@ -94,11 +106,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://oapi.dingtalk.com/sns/getuserinfo_bycode";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthDingTalkRequest.class;
+ }
},
/**
* 钉钉账号登录
*/
- DINGTALK_ACCOUNT(AuthDingTalkAccountRequest.class) {
+ DINGTALK_ACCOUNT {
@Override
public String authorize() {
return "https://oapi.dingtalk.com/connect/oauth2/sns_authorize";
@@ -113,11 +130,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return DINGTALK.userInfo();
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthDingTalkAccountRequest.class;
+ }
},
/**
* 百度
*/
- BAIDU(AuthBaiduRequest.class) {
+ BAIDU {
@Override
public String authorize() {
return "https://openapi.baidu.com/oauth/2.0/authorize";
@@ -142,11 +164,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://openapi.baidu.com/oauth/2.0/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthBaiduRequest.class;
+ }
},
/**
* csdn
*/
- CSDN(AuthCsdnRequest.class) {
+ CSDN {
@Override
public String authorize() {
return "https://api.csdn.net/oauth2/authorize";
@@ -161,6 +188,11 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.csdn.net/user/getinfo";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthCsdnRequest.class;
+ }
},
/**
* Coding,
@@ -168,7 +200,7 @@ public enum AuthDefaultSource implements AuthSource {
* 参考 https://help.coding.net/docs/project/open/oauth.html#%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83 中的说明,
* 新版的 coding API 地址需要传入用户团队名,这儿使用动态参数,方便在 request 中使用
*/
- CODING(AuthCodingRequest.class) {
+ CODING {
@Override
public String authorize() {
return "https://%s.coding.net/oauth_authorize.html";
@@ -183,11 +215,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://%s.coding.net/api/account/current_user";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthCodingRequest.class;
+ }
},
/**
* oschina 开源中国
*/
- OSCHINA(AuthOschinaRequest.class) {
+ OSCHINA {
@Override
public String authorize() {
return "https://www.oschina.net/action/oauth2/authorize";
@@ -202,11 +239,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://www.oschina.net/action/openapi/user";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthOschinaRequest.class;
+ }
},
/**
* 支付宝
*/
- ALIPAY(AuthAlipayRequest.class) {
+ ALIPAY {
@Override
public String authorize() {
return "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm";
@@ -221,11 +263,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://openapi.alipay.com/gateway.do";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthAlipayRequest.class;
+ }
},
/**
* QQ
*/
- QQ(AuthQqRequest.class) {
+ QQ {
@Override
public String authorize() {
return "https://graph.qq.com/oauth2.0/authorize";
@@ -245,11 +292,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://graph.qq.com/oauth2.0/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthQqRequest.class;
+ }
},
/**
* 微信开放平台
*/
- WECHAT_OPEN(AuthWeChatOpenRequest.class) {
+ WECHAT_OPEN {
@Override
public String authorize() {
return "https://open.weixin.qq.com/connect/qrconnect";
@@ -269,11 +321,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthWeChatOpenRequest.class;
+ }
},
/**
* 微信公众平台
*/
- WECHAT_MP(AuthWeChatMpRequest.class) {
+ WECHAT_MP {
@Override
public String authorize() {
return "https://open.weixin.qq.com/connect/oauth2/authorize";
@@ -293,11 +350,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthWeChatMpRequest.class;
+ }
},
/**
* 淘宝
*/
- TAOBAO(AuthTaobaoRequest.class) {
+ TAOBAO {
@Override
public String authorize() {
return "https://oauth.taobao.com/authorize";
@@ -312,11 +374,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
throw new AuthException(AuthResponseStatus.UNSUPPORTED);
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthTaobaoRequest.class;
+ }
},
/**
* Google
*/
- GOOGLE(AuthGoogleRequest.class) {
+ GOOGLE {
@Override
public String authorize() {
return "https://accounts.google.com/o/oauth2/v2/auth";
@@ -331,11 +398,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://www.googleapis.com/oauth2/v3/userinfo";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthGoogleRequest.class;
+ }
},
/**
* Facebook
*/
- FACEBOOK(AuthFacebookRequest.class) {
+ FACEBOOK {
@Override
public String authorize() {
return "https://www.facebook.com/v10.0/dialog/oauth";
@@ -350,11 +422,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://graph.facebook.com/v10.0/me";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthFacebookRequest.class;
+ }
},
/**
* 抖音
*/
- DOUYIN(AuthDouyinRequest.class) {
+ DOUYIN {
@Override
public String authorize() {
return "https://open.douyin.com/platform/oauth/connect";
@@ -374,11 +451,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://open.douyin.com/oauth/refresh_token/";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthDouyinRequest.class;
+ }
},
/**
* 领英
*/
- LINKEDIN(AuthLinkedinRequest.class) {
+ LINKEDIN {
@Override
public String authorize() {
return "https://www.linkedin.com/oauth/v2/authorization";
@@ -398,11 +480,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://www.linkedin.com/oauth/v2/accessToken";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthLinkedinRequest.class;
+ }
},
/**
* 微软
*/
- MICROSOFT(AuthMicrosoftRequest.class) {
+ MICROSOFT {
@Override
public String authorize() {
return "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
@@ -422,11 +509,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthMicrosoftRequest.class;
+ }
},
/**
* 小米
*/
- MI(AuthMiRequest.class) {
+ MI {
@Override
public String authorize() {
return "https://account.xiaomi.com/oauth2/authorize";
@@ -446,11 +538,16 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://account.xiaomi.com/oauth2/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthMiRequest.class;
+ }
},
/**
* 今日头条
*/
- TOUTIAO(AuthToutiaoRequest.class) {
+ TOUTIAO {
@Override
public String authorize() {
return "https://open.snssdk.com/auth/authorize";
@@ -465,11 +562,16 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://open.snssdk.com/data/user_profile";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthToutiaoRequest.class;
+ }
},
/**
* Teambition
*/
- TEAMBITION(AuthTeambitionRequest.class) {
+ TEAMBITION {
@Override
public String authorize() {
return "https://account.teambition.com/oauth2/authorize";
@@ -489,12 +591,17 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.teambition.com/users/me";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthTeambitionRequest.class;
+ }
},
/**
* 人人网
*/
- RENREN(AuthRenrenRequest.class) {
+ RENREN {
@Override
public String authorize() {
return "https://graph.renren.com/oauth/authorize";
@@ -514,12 +621,17 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.renren.com/v2/user/get";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthRenrenRequest.class;
+ }
},
/**
* Pinterest
*/
- PINTEREST(AuthPinterestRequest.class) {
+ PINTEREST {
@Override
public String authorize() {
return "https://api.pinterest.com/oauth";
@@ -534,12 +646,17 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.pinterest.com/v1/me";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthPinterestRequest.class;
+ }
},
/**
* Stack Overflow
*/
- STACK_OVERFLOW(AuthStackOverflowRequest.class) {
+ STACK_OVERFLOW {
@Override
public String authorize() {
return "https://stackoverflow.com/oauth";
@@ -554,6 +671,11 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.stackexchange.com/2.2/me";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthStackOverflowRequest.class;
+ }
},
/**
@@ -561,7 +683,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.10.0
*/
- HUAWEI(AuthHuaweiRequest.class) {
+ HUAWEI {
@Override
public String authorize() {
return "https://oauth-login.cloud.huawei.com/oauth2/v2/authorize";
@@ -581,6 +703,11 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthHuaweiRequest.class;
+ }
},
/**
@@ -588,7 +715,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.10.0
*/
- WECHAT_ENTERPRISE(AuthWeChatEnterpriseQrcodeRequest.class) {
+ WECHAT_ENTERPRISE {
@Override
public String authorize() {
return "https://open.work.weixin.qq.com/wwopen/sso/qrConnect";
@@ -603,12 +730,17 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthWeChatEnterpriseQrcodeRequest.class;
+ }
},
/**
* 企业微信网页登录
*/
- WECHAT_ENTERPRISE_WEB(AuthWeChatEnterpriseWebRequest.class) {
+ WECHAT_ENTERPRISE_WEB {
@Override
public String authorize() {
return "https://open.weixin.qq.com/connect/oauth2/authorize";
@@ -623,6 +755,11 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthWeChatEnterpriseWebRequest.class;
+ }
},
/**
@@ -630,7 +767,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.11.0
*/
- KUJIALE(AuthKujialeRequest.class) {
+ KUJIALE {
@Override
public String authorize() {
return "https://oauth.kujiale.com/oauth2/show";
@@ -650,6 +787,11 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://oauth.kujiale.com/oauth2/auth/token/refresh";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthKujialeRequest.class;
+ }
},
/**
@@ -657,7 +799,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.11.0
*/
- GITLAB(AuthGitlabRequest.class) {
+ GITLAB {
@Override
public String authorize() {
return "https://gitlab.com/oauth/authorize";
@@ -672,6 +814,11 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://gitlab.com/api/v4/user";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthGitlabRequest.class;
+ }
},
/**
@@ -679,7 +826,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.12.0
*/
- MEITUAN(AuthMeituanRequest.class) {
+ MEITUAN {
@Override
public String authorize() {
return "https://openapi.waimai.meituan.com/oauth/authorize";
@@ -699,6 +846,11 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://openapi.waimai.meituan.com/oauth/refresh_token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthMeituanRequest.class;
+ }
},
/**
@@ -708,7 +860,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.12.0
*/
- ELEME(AuthElemeRequest.class) {
+ ELEME {
@Override
public String authorize() {
return "https://open-api.shop.ele.me/authorize";
@@ -728,6 +880,11 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://open-api.shop.ele.me/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthElemeRequest.class;
+ }
},
/**
@@ -735,7 +892,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.13.0
*/
- TWITTER(AuthTwitterRequest.class) {
+ TWITTER {
@Override
public String authorize() {
return "https://api.twitter.com/oauth/authenticate";
@@ -750,6 +907,11 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://api.twitter.com/1.1/account/verify_credentials.json";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthTwitterRequest.class;
+ }
},
/**
@@ -759,7 +921,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.15.9
*/
- FEISHU(AuthFeishuRequest.class) {
+ FEISHU {
@Override
public String authorize() {
return "https://open.feishu.cn/open-apis/authen/v1/index";
@@ -779,13 +941,18 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://open.feishu.cn/open-apis/authen/v1/refresh_access_token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthFeishuRequest.class;
+ }
},
/**
* 京东
*
* @since 1.15.0
*/
- JD(AuthJdRequest.class) {
+ JD {
@Override
public String authorize() {
return "https://open-oauth.jd.com/oauth2/to_login";
@@ -805,12 +972,17 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://open-oauth.jd.com/oauth2/refresh_token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthJdRequest.class;
+ }
},
/**
* 阿里云
*/
- ALIYUN(AuthAliyunRequest.class) {
+ ALIYUN {
@Override
public String authorize() {
return "https://signin.aliyun.com/oauth2/v1/auth";
@@ -830,12 +1002,17 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://oauth.aliyun.com/v1/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthAliyunRequest.class;
+ }
},
/**
* 喜马拉雅
*/
- XMLY(AuthXmlyRequest.class) {
+ XMLY {
@Override
public String authorize() {
return "https://api.ximalaya.com/oauth2/js/authorize";
@@ -855,6 +1032,11 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://oauth.aliyun.com/v1/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthXmlyRequest.class;
+ }
},
/**
@@ -862,7 +1044,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
- AMAZON(AuthAmazonRequest.class) {
+ AMAZON {
@Override
public String authorize() {
return "https://www.amazon.com/ap/oa";
@@ -882,13 +1064,18 @@ public enum AuthDefaultSource implements AuthSource {
public String refresh() {
return "https://api.amazon.com/auth/o2/token";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthAmazonRequest.class;
+ }
},
/**
* Slack
*
* @since 1.16.0
*/
- SLACK(AuthSlackRequest.class) {
+ SLACK {
@Override
public String authorize() {
return "https://slack.com/oauth/v2/authorize";
@@ -915,13 +1102,18 @@ public enum AuthDefaultSource implements AuthSource {
public String revoke() {
return "https://slack.com/api/auth.revoke";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthSlackRequest.class;
+ }
},
/**
* line
*
* @since 1.16.0
*/
- LINE(AuthLineRequest.class) {
+ LINE {
@Override
public String authorize() {
return "https://access.line.me/oauth2/v2.1/authorize";
@@ -946,6 +1138,11 @@ public enum AuthDefaultSource implements AuthSource {
public String revoke() {
return "https://api.line.me/oauth2/v2.1/revoke";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthLineRequest.class;
+ }
},
/**
* Okta,
@@ -954,7 +1151,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
- OKTA(AuthOktaRequest.class) {
+ OKTA {
@Override
public String authorize() {
return "https://%s.okta.com/oauth2/%s/v1/authorize";
@@ -979,13 +1176,18 @@ public enum AuthDefaultSource implements AuthSource {
public String revoke() {
return "https://%s.okta.com/oauth2/%s/v1/revoke";
}
+
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthOktaRequest.class;
+ }
},
/**
* 程序员客栈
*
* @since 1.16.2
*/
- PROGINN(AuthProginnRequest.class) {
+ PROGINN {
@Override
public String authorize() {
return "https://www.proginn.com/oauth2/authorize";
@@ -1000,48 +1202,10 @@ public enum AuthDefaultSource implements AuthSource {
public String userInfo() {
return "https://www.proginn.com/openapi/user/basic_info";
}
- };
- /** 对应的实现类 */
- private Class extends AuthDefaultRequest> targetClass;
-
- AuthDefaultSource(Class extends AuthDefaultRequest> targetClass) {
- this.targetClass = targetClass;
- }
-
- /**
- * 根据source获取对应的AuthSource枚举
- * @param source 枚举名
- * @return AuthDefaultSource
- */
- public static AuthDefaultSource getAuthSource(String source){
- return Arrays.stream(AuthDefaultSource.values()).filter(authSource -> authSource.name().equalsIgnoreCase(source)).findAny().orElseThrow(()->new AuthException("未获取到有效的AuthSource配置"));
- }
-
- /**
- * 根据配置获取 AuthRequest 实例
- * @param authConfig 配置
- * @return AuthRequest
- */
- public AuthRequest getAuthRequestInstance(AuthConfig authConfig) {
- return getAuthRequestInstance(authConfig,null);
- }
-
- /**
- * 利用反射 生成 AuthRequest 实例
- * @param authConfig 配置
- * @param authStateCache 缓存配置
- * @return AuthRequest
- */
- public AuthRequest getAuthRequestInstance(AuthConfig authConfig, AuthStateCache authStateCache) {
- try {
- if(authStateCache==null){
- return this.targetClass.getDeclaredConstructor(AuthConfig.class).newInstance(authConfig);
- }else{
- return this.targetClass.getDeclaredConstructor(AuthConfig.class, AuthStateCache.class).newInstance(authConfig, authStateCache);
- }
- } catch (Exception e) {
- throw new AuthException("未获取到有效的Auth配置");
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthProginnRequest.class;
}
}
diff --git a/src/main/java/me/zhyd/oauth/config/AuthSource.java b/src/main/java/me/zhyd/oauth/config/AuthSource.java
index a6cde6460d2e6f2a429cc26110a09de9a0ed9b15..c7be23f49b96030ffd97fc99bcf2dc91bbd93a93 100644
--- a/src/main/java/me/zhyd/oauth/config/AuthSource.java
+++ b/src/main/java/me/zhyd/oauth/config/AuthSource.java
@@ -3,6 +3,7 @@ package me.zhyd.oauth.config;
import me.zhyd.oauth.enums.AuthResponseStatus;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.request.AuthDefaultRequest;
/**
* OAuth平台的API地址的统一接口,提供以下方法:
@@ -73,4 +74,11 @@ public interface AuthSource {
}
return this.getClass().getSimpleName();
}
+
+ /**
+ * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest}
+ *
+ * @return class
+ */
+ Class extends AuthDefaultRequest> getTargetClass();
}
diff --git a/src/test/java/me/zhyd/oauth/AuthRequestBuilderTest.java b/src/test/java/me/zhyd/oauth/AuthRequestBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..253e365791501db148626ab1625360a73c8fea32
--- /dev/null
+++ b/src/test/java/me/zhyd/oauth/AuthRequestBuilderTest.java
@@ -0,0 +1,105 @@
+package me.zhyd.oauth;
+
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.config.AuthDefaultSource;
+import me.zhyd.oauth.config.AuthExtendSource;
+import me.zhyd.oauth.request.AuthExtendRequest;
+import me.zhyd.oauth.request.AuthGiteeRequest;
+import me.zhyd.oauth.request.AuthGithubRequest;
+import me.zhyd.oauth.request.AuthRequest;
+import me.zhyd.oauth.utils.AuthStateUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AuthRequestBuilderTest {
+
+ /**
+ * 示例:一般场景下通过 AuthRequestBuilder 构建 AuthRequest
+ */
+ @Test
+ public void build2() {
+ AuthRequest authRequest = AuthRequestBuilder.builder()
+ .source("github")
+ .authConfig(AuthConfig.builder()
+ .clientId("a")
+ .clientSecret("a")
+ .redirectUri("https://www.justauth.cn")
+ .build())
+ .build();
+ Assert.assertTrue(authRequest instanceof AuthGithubRequest);
+ System.out.println(authRequest.authorize(AuthStateUtils.createState()));
+ }
+
+ /**
+ * 示例:AuthConfig 需要动态获取的场景下通过 AuthRequestBuilder 构建 AuthRequest
+ */
+ @Test
+ public void build() {
+ AuthRequest authRequest = AuthRequestBuilder.builder()
+ .source("gitee")
+ .authConfig((source) -> {
+ // 通过 source 动态获取 AuthConfig
+ // 此处可以灵活的从 sql 中取配置也可以从配置文件中取配置
+ return AuthConfig.builder()
+ .clientId(source)
+ .clientSecret(source)
+ .redirectUri("https://www.justauth.cn/" + source)
+ .build();
+ })
+ .build();
+ Assert.assertTrue(authRequest instanceof AuthGiteeRequest);
+ System.out.println(authRequest.authorize(AuthStateUtils.createState()));
+ }
+
+ /**
+ * 示例:自定义实现的 AuthRequest,通过 AuthRequestBuilder 构建 AuthRequest
+ */
+ @Test
+ public void build3() {
+ AuthRequest authRequest = AuthRequestBuilder.builder()
+ // 关键点:将自定义的 AuthSource 配置上
+ .extendSource(AuthExtendSource.values())
+ .source("other")
+ .authConfig(AuthConfig.builder()
+ .clientId("a")
+ .clientSecret("a")
+ .redirectUri("https://www.justauth.cn")
+ .build())
+ .build();
+ Assert.assertTrue(authRequest instanceof AuthExtendRequest);
+ System.out.println(authRequest.authorize(AuthStateUtils.createState()));
+ }
+
+ /**
+ * 测试不同平台
+ */
+ @Test
+ public void build4() {
+ for (AuthDefaultSource value : AuthDefaultSource.values()) {
+ if (value == AuthDefaultSource.TWITTER) {
+ System.out.println(value.getTargetClass());
+ System.out.println("忽略 twitter");
+ continue;
+ }
+ AuthRequest authRequest = AuthRequestBuilder.builder()
+ .source(value.getName())
+ .authConfig(AuthConfig.builder()
+ .clientId("a")
+ .clientSecret("a")
+ .redirectUri("https://www.justauth.cn")
+ .alipayPublicKey("asd")
+ .authServerId("asd")
+ .agentId("asd")
+ .domainPrefix("asd")
+ .stackOverflowKey("asd")
+
+ .deviceId("asd")
+ .clientOsType(3)
+ .build())
+ .build();
+ System.out.println(value.getTargetClass());
+ System.out.println(authRequest.authorize(AuthStateUtils.createState()));
+ }
+
+ }
+}
diff --git a/src/test/java/me/zhyd/oauth/config/AuthExtendSource.java b/src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
index 9f57097a717fcaf4fc6a7c223ea7fb941f594735..c1262bb536777ad1f565f3681d377c0bab8d82a3 100644
--- a/src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
+++ b/src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
@@ -1,10 +1,7 @@
package me.zhyd.oauth.config;
-import me.zhyd.oauth.cache.AuthStateCache;
-import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthExtendRequest;
-import me.zhyd.oauth.request.AuthRequest;
/**
* 测试自定义实现{@link AuthSource}接口后的枚举类
@@ -15,7 +12,7 @@ import me.zhyd.oauth.request.AuthRequest;
*/
public enum AuthExtendSource implements AuthSource {
- OTHER (AuthExtendRequest.class){
+ OTHER {
/**
* 授权的api
*
@@ -65,27 +62,10 @@ public enum AuthExtendSource implements AuthSource {
public String refresh() {
return null;
}
- };
- private Class extends AuthDefaultRequest> targetClass;
-
- AuthExtendSource(Class extends AuthDefaultRequest> targetClass) {
- this.targetClass = targetClass;
- }
-
- public AuthRequest getAuthRequestInstance(AuthConfig authConfig) {
- return this.getAuthRequestInstance(authConfig,null);
- }
-
- public AuthRequest getAuthRequestInstance(AuthConfig authConfig, AuthStateCache authStateCache) {
- try {
- if(authStateCache==null){
- return this.targetClass.getDeclaredConstructor(AuthConfig.class).newInstance(authConfig);
- }else{
- return this.targetClass.getDeclaredConstructor(AuthConfig.class, AuthStateCache.class).newInstance(authConfig, authStateCache);
- }
- } catch (Exception e) {
- throw new AuthException("未获取到有效的Auth配置");
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthExtendRequest.class;
}
}
diff --git a/src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java b/src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
index c820d8fcec9891f0ba3c22913c3710099a3ab959..1fd144af8f790b21b02e4a360bf397e1d30ee482 100644
--- a/src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
+++ b/src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
@@ -1,9 +1,7 @@
package me.zhyd.oauth.request;
import me.zhyd.oauth.config.AuthConfig;
-import me.zhyd.oauth.config.AuthDefaultSource;
import me.zhyd.oauth.utils.AuthStateUtils;
-import org.junit.Assert;
import org.junit.Test;
public class AuthWeChatMpRequestTest {
@@ -18,15 +16,4 @@ public class AuthWeChatMpRequestTest {
.build());
System.out.println(request.authorize(AuthStateUtils.createState()));
}
-
- @Test
- public void authorize1() {
- AuthRequest request = AuthDefaultSource.getAuthSource("wechat_mp").getAuthRequestInstance(AuthConfig.builder()
- .clientId("a")
- .clientSecret("a")
- .redirectUri("https://www.justauth.cn")
- .build());
- Assert.assertTrue(request instanceof AuthWeChatMpRequest);
- System.out.println(request.authorize(AuthStateUtils.createState()));
- }
}