Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10df9f05f3 | |||
| fd183afd4a | |||
| d48a62d5cb | |||
| b466dd8de3 | |||
| 4d8411e978 | |||
| cf77e4d0e0 | |||
| 4f303705d9 | |||
| 1fb8be6c82 | |||
| 48a368b516 | |||
| 6594d90a71 | |||
| 31c983234f | |||
| 52682debfb | |||
| d5e161eaef | |||
| 1ab1cc124a | |||
| 050686d85f | |||
| 05f95b86b4 | |||
| 665daa37b2 | |||
| 576402eec3 | |||
| ec6c7a92b6 | |||
| d44cbd6e2b | |||
| 15caef01d3 | |||
| ad2e7c8231 | |||
| 57a7b7ff17 | |||
| 7a40159d15 | |||
| bcb27e4118 | |||
| 0b9cb95103 | |||
| d61bb58b93 | |||
| d034722232 | |||
| 197f15dc4f | |||
| fcb6fd9937 | |||
| ce5c437289 | |||
| fabfff60c9 | |||
| d4296d160e | |||
| d9967b2814 | |||
| 267b74bed7 | |||
| 3e8c475d3f | |||
| c1f9e96a92 | |||
| bed01eef6d | |||
| 909702e4da | |||
| 57cb7fb0d1 | |||
| b9c29c7534 | |||
| 6474c46505 | |||
| 864665f1b8 | |||
| 83d23302f8 | |||
| ca1522adfd | |||
| 55459652b9 | |||
| 92bc4ab34a | |||
| 4fab7561a4 | |||
| 16918ea13f |
@@ -1,13 +1,12 @@
|
||||
### 哪个平台?
|
||||
为更快的帮您定位问题,推荐您用以下模板反馈问题:
|
||||
|
||||
### 1. 出现问题时,您做了哪些操作?
|
||||
|
||||
### 2. 在哪个步骤出现了问题?
|
||||
|
||||
### 重现步骤
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
### 3. 您希望得到什么结果?
|
||||
|
||||
### 4. 您实际得到什么结果?
|
||||
|
||||
### 5. 请附上您出现问题的整屏截图或者整个异常堆栈信息
|
||||
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
### 该Pull Request关联的Issue
|
||||
[ ] 是否为解决Issue?
|
||||
|
||||
|
||||
### 修改描述
|
||||
|
||||
|
||||
|
||||
### 测试用例
|
||||
|
||||
|
||||
|
||||
### 修复效果的截屏
|
||||
### 您做了哪些更新?
|
||||
|
||||
#### 新增
|
||||
|
||||
#### 修改
|
||||
|
||||
#### 修复
|
||||
|
||||
#### 其他
|
||||
|
||||
|
||||
### 是否做了充分测试?
|
||||
|
||||
- [ ] 是,已经做过测试,并且测试通过
|
||||
- [ ] 否,还没做测试,需要作者自测
|
||||
|
||||
注:测试demo可以使用:
|
||||
- [Springboot版](https://gitee.com/yadong.zhang/JustAuth-demo)
|
||||
- [jFinal版](https://github.com/xkcoding/jfinal-justauth-demo)
|
||||
- [ActFramework版](https://github.com/xkcoding/act-justauth-demo)
|
||||
|
||||
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
language: java
|
||||
|
||||
sudo: false # faster builds
|
||||
|
||||
install: true
|
||||
|
||||
jdk:
|
||||
- openjdk8
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
script:
|
||||
- export TZ=Asia/Shanghai
|
||||
- mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
|
||||
- mvn cobertura:cobertura -Dcobertura.report.format=xml -Dmaven.javadoc.skip.true
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
@@ -6,7 +6,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.9.4-blue.svg" ></img>
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.10.1-blue.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://gitee.com/yadong.zhang/JustAuth/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/apm/l/vim-mode.svg?color=yellow" ></img>
|
||||
@@ -14,8 +14,20 @@
|
||||
<a target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/">
|
||||
<img src="https://img.shields.io/badge/Docs-1.9.4-orange.svg" ></img>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.10.1-orange.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://docs.justauth.whnb.wang" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/zhangyd-c/JustAuth">
|
||||
<img src="https://codecov.io/gh/zhangyd-c/JustAuth/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href='https://gitee.com/yadong.zhang/JustAuth/stargazers'>
|
||||
<img src='https://gitee.com/yadong.zhang/JustAuth/badge/star.svg?theme=white' alt='star'></img>
|
||||
</a>
|
||||
<a target="_blank" href='https://github.com/zhangyd-c/JustAuth'>
|
||||
<img src="https://img.shields.io/github/stars/zhangyd-c/JustAuth.svg?style=social" alt="github star"></img>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -49,6 +61,8 @@
|
||||
<td align="center" width="200"><a href="#授权人人"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/renren.png" width="20"></a></td>
|
||||
<td align="center" width="200"><a href="#授权Pinterest"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/pinterest.png" width="20"></a></td>
|
||||
<td align="center" width="200"><a href="#授权Stack Overflow"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/stackoverflow.png" width="20"></a></td>
|
||||
<td align="center" width="200"><a href="#授权华为"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/huawei.png" width="20"></a></td>
|
||||
<td align="center" width="200"><a href="#授权微信企业版" title="微信企业版"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechat.png" width="20"></a></td>
|
||||
<td align="center" width="200"><a href="#授权csdn"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="20"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -60,7 +74,8 @@
|
||||
|
||||
JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具类库**,它可以让我们脱离繁琐的第三方登录SDK,让登录变得**So easy!**
|
||||
|
||||
项目开源地址:[gitee](https://gitee.com/yadong.zhang/JustAuth) | [github](https://github.com/zhangyd-c/JustAuth)
|
||||
项目开源地址:[gitee](https://gitee.com/yadong.zhang/JustAuth) | [github](https://github.com/zhangyd-c/JustAuth)
|
||||
项目文档:[参考文档](https://docs.justauth.whnb.wang)
|
||||
|
||||
## 特点
|
||||
|
||||
@@ -76,7 +91,7 @@ JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<version>1.10.1</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
@@ -139,6 +154,8 @@ authRequest.login(callback);
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/renren.png" width="20"> | [AuthRenrenRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java) | <a href="http://open.renren.com/wiki/OAuth2.0" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/pinterest.png" width="20"> | [AuthPinterestRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java) | <a href="https://developers.pinterest.com/docs/api/overview/?" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/stackoverflow.png" width="20"> | [AuthStackOverflowRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java) | <a href="https://api.stackexchange.com/docs/authentication" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/huawei.png" width="20"> | [AuthHuaweiRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthHuaweiRequest.java) | <a href="https://developer.huawei.com/consumer/cn/devservice/doc/30101" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechat.png" width="20"> | [AuthWeChatEnterpriseRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthWeChatEnterpriseRequest.java) | <a href="https://open.work.weixin.qq.com/api/doc#90000/90135/90664" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="20"> | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 |
|
||||
|
||||
_请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经下线。如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了_
|
||||
@@ -166,6 +183,8 @@ _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经
|
||||
|
||||
[阿里妈妈MUX倾力打造的矢量图标库-iconfont](https://www.iconfont.cn/search/index): 本文档中的图标大部分取自该平台
|
||||
|
||||
[mica](https://github.com/lets-mica/mica):Spring Cloud 微服务开发核心包,支持 `web `和 `webflux`。注:JustAuth项目中的[UuidUtils](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/utils/UuidUtils.java)就是直接使用的mica提供的高性能的uuid创建工具类源码[StringUtil.java](https://github.com/lets-mica/mica/blob/master/mica-core/src/main/java/net/dreamlu/mica/core/utils/StringUtil.java#L335)
|
||||
|
||||
## 关于OAuth
|
||||
|
||||
[The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
|
||||
@@ -180,7 +199,7 @@ _请知悉:经咨询CSDN官方客服得知,CSDN的授权开放平台已经
|
||||
|
||||
- JustAuth交流群 (230017570):专业交流该项目
|
||||
|
||||
- 开源总群 (190886500):各个开源项目的都有,也有博客建设等方面的朋友。(注意,该群需付费进入,防止发垃圾广告、垃圾推广等人士)
|
||||
- 开源总群 (190886500):各个开源项目的都有,也有博客建设等方面的朋友。
|
||||
|
||||
|
||||
## 请喝咖啡
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
## ~~升级到1.8.0后如何启用state?~~
|
||||
|
||||
~~在原api使用方法的基础上,为config追加一个state即可。~~
|
||||
```
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.state("state") // 就是这儿
|
||||
.build());
|
||||
```
|
||||
|
||||
## ~~升级到1.8.0后login方法报错?~~
|
||||
|
||||
~~这是因为1.8.0版本中新增了[AuthCallback](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/model/AuthCallback.java)类,这个类封装了所有可能的回调参数。目前包含以下三个参数:~~
|
||||
- ~~`code`: 访问AuthorizeUrl后回调时带的参数code,用来换取token~~
|
||||
- ~~`auth_code`: 支付宝授权登陆时不会返回code而是返回`auth_code`参数~~
|
||||
- ~~`state`: 访问AuthorizeUrl后回调时带的参数state,用于和请求AuthorizeUrl前的state比较,防止CSRF攻击~~
|
||||
|
||||
~~1.8.0版本之后的api,可以直接用AuthCallback类作为回调方法的入参,比如:~~
|
||||
```
|
||||
@RequestMapping("/callback/{source}")
|
||||
public Object login(@PathVariable("source") String source, AuthCallback callback) {
|
||||
System.out.println("进入callback:" + source + " callback params:" + JSONObject.toJSONString(callback));
|
||||
AuthRequest authRequest = getAuthRequest(source);
|
||||
AuthResponse response = authRequest.login(callback);
|
||||
System.out.println(JSONObject.toJSONString(response));
|
||||
return response;
|
||||
}
|
||||
```
|
||||
~~_代码截取自_ :https://gitee.com/yadong.zhang/JustAuth-demo~~
|
||||
|
||||
## ~~升级到1.8.0后对于state参数有什么特殊要求吗?~~
|
||||
|
||||
~~理论上没有,stata只是用来保持会话状态,因为http协议的无状态性,从授权到回调,无法感知具体是哪个用户触发的。所以可以使用state作为校验。注:state参数每次完整的授权链中只可用一次!(也是为了防止不必要的危险)~~
|
||||
|
||||
~~作者建议state命名格式如下:~~
|
||||
- ~~授权登录:`{source}_{ip}_{random}`~~
|
||||
- ~~账号绑定:`{source}_{userId}_{ip}_{random}`~~
|
||||
|
||||
~~其中`source`表示授权平台,可以直接去JustAuth中的source,`ip`为当前用户的ip(部分情况可能不适用),`random`为随机字符串,`userId`为当前登录用户的id。~~
|
||||
|
||||
~~注:`authorize`和`login`(不是指回调传回的`state`,而是声明`request`时传入的`state`)中传的`state`务必保证一致~~
|
||||
|
||||
## 升级到1.9.3+版本后编译失败
|
||||
|
||||
主要明显的就是`IpUtils.getIp`和request的`.state`报错。
|
||||
|
||||
这是因为从`v1.9.3`版本开始,对项目进行了一些优化,具体优化内容参考:[v1.9.3](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.3)和[v1.9.4](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.4)。
|
||||
|
||||
新版本的使用方式,参考[JustAuth-demo](https://gitee.com/yadong.zhang/JustAuth-demo/blob/master/src/main/java/me/zhyd/justauth/RestAuthController.java)
|
||||
```
|
||||
@RequestMapping("/render/{source}")
|
||||
public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
|
||||
AuthRequest authRequest = getAuthRequest(source);
|
||||
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
|
||||
response.sendRedirect(authorizeUrl);
|
||||
}
|
||||
@RequestMapping("/callback/{source}")
|
||||
public Object login(@PathVariable("source") String source, AuthCallback callback) {
|
||||
AuthRequest authRequest = getAuthRequest(source);
|
||||
AuthResponse response = authRequest.login(callback);
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
## 升级到最新版本后为什么支付宝登录不能用了?
|
||||
|
||||
在升级到新版后,使用支付宝登录会提示`ClassNotFoundExcption`异常,这是因为从`1.9.4`版本开始,JustAuth将不在强依赖`alipay-sdk-java`,如果你需要用到Alipay的授权登陆,那么你还需要添加以下依赖:
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>3.7.4.ALL</version>
|
||||
</dependency>
|
||||
```
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
<p align="center">
|
||||
<a href="https://www.justauth.cn/"><img src="./_media/cover.png" width="400"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>Login, so easy!</strong>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>史上最全的整合第三方登录的开源库</strong>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.10.1-blue.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://gitee.com/yadong.zhang/JustAuth/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/apm/l/vim-mode.svg?color=yellow" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.10.1-orange.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://docs.justauth.whnb.wang" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/zhangyd-c/JustAuth">
|
||||
<img src="https://codecov.io/gh/zhangyd-c/JustAuth/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href='https://gitee.com/yadong.zhang/JustAuth/stargazers'>
|
||||
<img src='https://gitee.com/yadong.zhang/JustAuth/badge/star.svg?theme=white' alt='star'></img>
|
||||
</a>
|
||||
<a target="_blank" href='https://github.com/zhangyd-c/JustAuth'>
|
||||
<img src="https://img.shields.io/github/stars/zhangyd-c/JustAuth.svg?style=social" alt="github star"></img>
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>开源地址:</strong> <a target="_blank" href='https://gitee.com/yadong.zhang/JustAuth'>Gitee</a> | <a target="_blank" href='https://github.com/zhangyd-c/JustAuth'>Github</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>QQ群:</strong>230017570
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>文档更新日期:</strong> {docsify-updated}
|
||||
</p>
|
||||
|
||||
## 简介
|
||||
|
||||
JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具类库**,它可以让我们脱离繁琐的第三方登录SDK,让登录变得**So easy!**
|
||||
|
||||
## 特点
|
||||
|
||||
废话不多说,就俩字:
|
||||
|
||||
1. **全**:已集成十多家第三方平台(国内外常用的基本都已包含),后续依然还有扩展计划!
|
||||
2. **简**:API就是奔着最简单去设计的,尽量让您用起来没有障碍感!
|
||||
|
||||
## 已集成的平台
|
||||
|
||||
| :computer: 平台 | :coffee: API类 | :page_facing_up: SDK |
|
||||
|:------:|:-------:|:-------:|
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/gitee.png" width="20"> | [AuthGiteeRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGiteeRequest.java) | <a href="https://gitee.com/api/v5/oauth_doc#list_1" target="_blank">参考文档</a> |
|
||||
| <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) | <a href="https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/" target="_blank">参考文档</a> |
|
||||
| <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) | <a href="https://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/dingtalk.png" width="20"> | [AuthDingTalkRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthDingTalkRequest.java) | <a href="https://open-doc.dingtalk.com/microapp/serverapi2/kymkv6" target="_blank">参考文档</a> |
|
||||
| <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) | <a href="http://developer.baidu.com/wiki/index.php?title=docs/oauth" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/coding.png" width="25"> | [AuthCodingRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCodingRequest.java) | <a href="https://open.coding.net/references/oauth/" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/tencentCloud.png" width="25"> | [AuthTencentCloudRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTencentCloudRequest.java) | <a href="https://dev.tencent.com/help/doc/faq/b4e5b7aee786/oauth" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/oschina.png" width="20"> | [AuthOschinaRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthOschinaRequest.java) | <a href="https://www.oschina.net/openapi/docs/oauth2_authorize" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/alipay.png" width="20"> | [AuthAlipayRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java) | <a href="https://alipay.open.taobao.com/docs/doc.htm?spm=a219a.7629140.0.0.336d4b70GUKXOl&treeId=193&articleId=105809&docType=1" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/qq.png" width="20"> | [AuthQqRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthQqRequest.java) | <a href="https://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechat.png" width="20"> | [AuthWeChatRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthWeChatRequest.java) | <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/taobao.png" width="20"> | [AuthTaobaoRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTaobaoRequest.java) | <a href="https://open.taobao.com/doc.htm?spm=a219a.7386797.0.0.4e00669acnkQy6&source=search&docId=105590&docType=1" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/google.png" width="20"> | [AuthGoogleRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java) | <a href="https://developers.google.com/identity/protocols/OpenIDConnect" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/facebook.png" width="20"> | [AuthFacebookRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthFacebookRequest.java) | <a href="https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/douyin.png" width="20"> | [AuthDouyinRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java) | <a href="https://www.douyin.com/platform/doc/m-2-1-1" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/linkedin.png" width="20"> | [AuthLinkedinRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthLinkedinRequest.java) | <a href="https://docs.microsoft.com/zh-cn/linkedin/shared/authentication/authorization-code-flow?context=linkedin/context" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/microsoft.png" width="20"> | [AuthMicrosoftRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthMicrosoftRequest.java) | <a href="https://docs.microsoft.com/zh-cn/graph/auth/" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/mi.png" width="20"> | [AuthMiRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthMiRequest.java) | <a href="https://dev.mi.com/console/doc/detail?pId=711" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/toutiao.png" width="20"> | [AuthToutiaoRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthToutiaoRequest.java) | <a href="https://open.mp.toutiao.com/#/resource?_k=y7mfgk" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/teambition.png" width="20"> | [AuthTeambitionRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthTeambitionRequest.java) | <a href="https://docs.teambition.com/" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/renren.png" width="20"> | [AuthRenrenRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthRenrenRequest.java) | <a href="http://open.renren.com/wiki/OAuth2.0" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/pinterest.png" width="20"> | [AuthPinterestRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthPinterestRequest.java) | <a href="https://developers.pinterest.com/docs/api/overview/?" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/stackoverflow.png" width="20"> | [AuthStackOverflowRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthStackOverflowRequest.java) | <a href="https://api.stackexchange.com/docs/authentication" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/huawei.png" width="20"> | [AuthHuaweiRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthHuaweiRequest.java) | <a href="https://developer.huawei.com/consumer/cn/devservice/doc/30101" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/wechat.png" width="20"> | [AuthWeChatEnterpriseRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthWeChatEnterpriseRequest.java) | <a href="https://open.work.weixin.qq.com/api/doc#90000/90135/90664" target="_blank">参考文档</a> |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/csdn.png" width="20"> | [AuthCsdnRequest](https://gitee.com/yadong.zhang/JustAuth/blob/master/src/main/java/me/zhyd/oauth/request/AuthCsdnRequest.java) | 无 |
|
||||
|
||||
|
||||
## 快速开始
|
||||
|
||||
- 引入依赖
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.10.1</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
```java
|
||||
// 创建授权request
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build());
|
||||
// 生成授权页面
|
||||
authRequest.authorize();
|
||||
// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的参数
|
||||
// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
|
||||
authRequest.login(callback);
|
||||
```
|
||||
|
||||
## 贡献代码
|
||||
|
||||
1. fork本项目到自己的repo
|
||||
2. 把fork过去的项目也就是你仓库中的项目clone到你的本地
|
||||
3. 修改代码
|
||||
4. commit后push到自己的库
|
||||
5. 发起PR(pull request) 请求,提交到`dev`分支
|
||||
6. 等待作者合并
|
||||
|
||||
_注:JustAuth只接受集成oauth2.0的平台_
|
||||
|
||||
## 关于功能尝鲜
|
||||
|
||||
JustAuth一共有两个主要分支:
|
||||
- 线上版分支(master):稳定版,发布版就是这个分支的代码
|
||||
- 开发版分支(dev):不保证稳定,新功能都会优先推送到该分支,对于想尝鲜的朋友,可以直接下载代码,然后源码编译dev分支
|
||||
|
||||
|
||||
## 捐赠
|
||||
|
||||
| 支付宝 | 微信 |
|
||||
| :------------: | :------------: |
|
||||
| <img src="https://gitee.com/yadong.zhang/static/raw/master/qrcode/zfb_code.png" width="200"/> | <img src="https://gitee.com/yadong.zhang/static/raw/master/qrcode/wx_code.png" width="200" /> |
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||

|
||||
# JustAuth <small>1.10.1</small>
|
||||
|
||||
<strong>史上最全的整合第三方登录的开源库</strong>
|
||||
|
||||
<strong>Login, so easy</strong>
|
||||
|
||||
<p>已集成国内外十多家平台</p>
|
||||
<p>极简的API设计</p>
|
||||
|
||||
|
||||
[Gitee](https://gitee.com/yadong.zhang/JustAuth)
|
||||
[Github](https://github.com/zhangyd-c/JustAuth)
|
||||
[Get Started](#简介)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,12 @@
|
||||
- [入门](README.md)
|
||||
- [更新记录](update.md)
|
||||
- 引导
|
||||
- [如何使用JustAuth集成一个平台](how-to-use.md)
|
||||
- [获取授权链接](authorize.md)
|
||||
- [登录](login.md)
|
||||
- 其他特性
|
||||
- [使用State](using-state.md)
|
||||
- [自定义state缓存](customize-the-state-cache.md)
|
||||
- [配套项目](supporting.md)
|
||||
- [Q&A](Q&A.md)
|
||||
- [Who is using](users.md)
|
||||
@@ -0,0 +1,3 @@
|
||||
# 获取授权链接
|
||||
|
||||
待补充
|
||||
@@ -0,0 +1,3 @@
|
||||
# 自定义state缓存
|
||||
|
||||
待补充
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1021 B |
@@ -0,0 +1,3 @@
|
||||
# 如何使用JustAuth集成一个平台
|
||||
|
||||
待补充
|
||||
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>JustAuth - 史上最全的整合第三方登录的开源库</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
|
||||
<meta name="description" content="JustAuth,史上最全的整合第三方登录的开源库" />
|
||||
<meta name="keywords" content="JustAuth,第三方授权登录,OAuth" />
|
||||
|
||||
<meta itemprop="name" content="JustAuth,史上最全的整合第三方登录的开源库" />
|
||||
<meta itemprop="description" content="JustAuth,如你所见,它仅仅是一个第三方授权登录的工具类库,它可以让我们脱离繁琐的第三方登录SDK,让登录变得So easy!" />
|
||||
<meta itemprop="image" content="./_media/cover.png" />
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||
<!-- 百度统计 -->
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?4c7a1a462477545b480a3dd1ed95f0a9";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">Please wait...</div>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: '<img src="./_media/cover.png" width="200"><br>Login, so easy',
|
||||
search: {
|
||||
maxAge: 86400000,
|
||||
noData: {
|
||||
'/': '找不到结果'
|
||||
},
|
||||
paths: 'auto',
|
||||
placeholder: {
|
||||
'/': '搜索'
|
||||
}
|
||||
},
|
||||
repo: 'https://gitee.com/yadong.zhang/JustAuth',
|
||||
loadSidebar: true,
|
||||
maxLevel: 4,
|
||||
subMaxLevel: 2,
|
||||
auto2top: true,
|
||||
coverpage: true,
|
||||
formatUpdated: '{YYYY}/{MM}/{DD} {HH}:{mm}:{ss}',
|
||||
}
|
||||
</script>
|
||||
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
# 登录
|
||||
|
||||
待补充
|
||||
@@ -0,0 +1,8 @@
|
||||
## 配套demo
|
||||
- [Springboot版](https://gitee.com/yadong.zhang/JustAuth-demo) :JustAuth项目的demo(springboot项目)
|
||||
- [jFinal版](https://github.com/xkcoding/jfinal-justauth-demo) :Jfinal集成JustAuth的demo
|
||||
- [ActFramework版](https://github.com/xkcoding/act-justauth-demo) :ActFramework 集成 JustAuth 的 demo
|
||||
|
||||
## 插件
|
||||
- [justauth-spring-boot-starter](https://github.com/xkcoding/justauth-spring-boot-starter) :Spring Boot 集成 JustAuth 的最佳实践
|
||||
|
||||
+76
-21
@@ -1,11 +1,50 @@
|
||||
### 2019/07/30 ([v1.9.4](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.4))
|
||||
## v1.10.1
|
||||
### 2019/08/17
|
||||
|
||||
- AuthUser添加构造函数,支持反序列化
|
||||
|
||||
### 2019/08/08
|
||||
|
||||
- 项目迁移到组织[justauth](https://github.com/justauth)
|
||||
|
||||
## v1.10.0
|
||||
### 2019/08/06
|
||||
|
||||
- 合并[PR-34](https://github.com/zhangyd-c/JustAuth/pull/34),添加StringUtil单元测试,修复bug
|
||||
- 合并[PR-35](https://github.com/zhangyd-c/JustAuth/pull/35),集成企业微信
|
||||
|
||||
### 2019/08/05
|
||||
|
||||
- 集成华为登录
|
||||
- 修改`AuthChecker#checkCode`方法,对于不同平台使用不同参数接受code的情况统一做处理
|
||||
|
||||
### 2019/08/03
|
||||
|
||||
合并github上[xkcoding](https://github.com/xkcoding) 的[pr#32](https://github.com/zhangyd-c/JustAuth/pull/32),抽取 cache 接口,方便用户自行集成 cache
|
||||
|
||||
### 2019/08/02
|
||||
|
||||
- 增加`AuthCache`配置类`AuthCacheConfig.java`,可以自定义缓存有效期以及是否开启定时任务
|
||||
- 去掉`slf4j`依赖,封装`Log.java`工具类
|
||||
- 规范测试类
|
||||
|
||||
## v1.9.5
|
||||
### 2019/07/31
|
||||
|
||||
`v1.9.4`版本发布失败,请升级到`1.9.5`版本!
|
||||
|
||||
由此给您带来的不便,敬请谅解!
|
||||
|
||||
## v1.9.4
|
||||
### 2019/07/30
|
||||
|
||||
1. 升级`hutool-http`版本到`v4.6.1`
|
||||
2. 去除`AuthCallback`中增加的默认的校验state的方法,挪到`AuthDefaultRequest`中做统一处理
|
||||
3. `alipay-sdk-java`依赖改为`provided`,如果需要使用支付宝登录,需要使用方手动引入相关依赖,具体操作方式,见项目WIKI;
|
||||
4. 规范注释
|
||||
|
||||
### 2019/07/30 ([v1.9.3](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.3))
|
||||
## v1.9.3
|
||||
### 2019/07/30
|
||||
|
||||
1. 规范注释
|
||||
2. 增加State缓存,`AuthCallback`中增加默认的校验state的方法
|
||||
@@ -24,15 +63,18 @@
|
||||
2. 删除`AuthState`类
|
||||
3. 增加`authorize(String)`方法,并且使用`@Deprecated`标记`authorize()`方法
|
||||
|
||||
### 2019/07/22 ([v1.9.2](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.2))
|
||||
## v1.9.2
|
||||
### 2019/07/22
|
||||
1. 合并github上[xkcoding](https://github.com/xkcoding) 的[pr#26](https://github.com/zhangyd-c/JustAuth/pull/26),AuthConfig类添加lombok注解,方便 [justauth-spring-boot-starter](https://github.com/xkcoding/justauth-spring-boot-starter) 直接使用
|
||||
|
||||
### 2019/07/22 ([v1.9.1](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.1))
|
||||
## v1.9.1
|
||||
### 2019/07/22
|
||||
1. 增加`stackoverflow`参数校验
|
||||
2. 解决`Pinterest`获取用户失败的问题
|
||||
3. 添加注释
|
||||
|
||||
### 2019/07/19 ([v1.9.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.9.0))
|
||||
## v1.9.0
|
||||
### 2019/07/19
|
||||
|
||||
1. 合并github上[@dyc12ii](https://github.com/dyc12ii) 的[pr#25](https://github.com/zhangyd-c/JustAuth/pull/25),升级fastjson版本至1.2.58,避免安全漏洞
|
||||
2. `AuthUserGender`枚举类挪到`enums`包下
|
||||
@@ -62,13 +104,15 @@
|
||||
4. `ResponseStatus` 改名为 `AuthResponseStatus` 并且移动到 `me.zhyd.oauth.model`
|
||||
5. 合并github上[@xkcoding](https://github.com/xkcoding) 的[pr#18](https://github.com/zhangyd-c/JustAuth/pull/18),修复小米回调错误问题 同时 支持微信获取unionId
|
||||
|
||||
### 2019/07/15 ([v1.8.1](https://gitee.com/yadong.zhang/JustAuth/releases/v1.8.1))
|
||||
## v1.8.1
|
||||
### 2019/07/15
|
||||
1. 新增 `AuthState` 类,内置默认的state生成规则和校验规则
|
||||
|
||||
### 2019/07/12
|
||||
1. 合并[Braavos96](https://github.com/Braavos96)提交的[PR#16](https://github.com/zhangyd-c/JustAuth/pull/16)
|
||||
|
||||
### 2019/06/28 ([v1.8.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.8.0))
|
||||
## v1.8.0
|
||||
### 2019/06/28
|
||||
1. 修复百度登录获取不到token失效时间的问题
|
||||
2. 增加state参数校验,预防CSRF。**强烈建议启用state**!
|
||||
|
||||
@@ -81,14 +125,17 @@
|
||||
|
||||
由于state安全问题,1.8.0以前的版本都有隐藏的CSRF漏洞问题,所以强烈建议正在使用JustAuth的朋友升级到1.8.0版本!
|
||||
|
||||
### 2019/06/25 ([v1.7.1](https://gitee.com/yadong.zhang/JustAuth/releases/v1.7.1))
|
||||
## v1.7.1
|
||||
### 2019/06/25
|
||||
qq授权登录时,需要获取`openId`作为`uuid`,在`1.6.1-beta`和`1.7.0`版本中,引入了`unionId`这一属性。获取`unionid`需要单独向qq团队**发送邮件**申请权限,鉴于这一申请权限的步骤比较麻烦(需要填写的内容比较多),所以在`AuthConfig`中增加了一个`unionId`属性,当为**true**时才会获取unionid,当为false时只获取openId。如果你需要该功能, 则在自行申请了相关权限后,将该属性置为true即可。关于unionId的参考链接:[UnionID介绍](http://wiki.connect.qq.com/unionid%E4%BB%8B%E7%BB%8D)
|
||||
|
||||
### 2019/06/19 ([v1.7.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.7.0))
|
||||
## v1.7.0
|
||||
### 2019/06/19
|
||||
1. 合并[xkcoding](https://github.com/xkcoding)提交的[PR](https://github.com/zhangyd-c/JustAuth/pull/14),重构了部分代码,jar包由原来的`130+kb`优化到现在的`110+kb`
|
||||
2. 合并[skqing](https://gitee.com/skqing)提交的[PR](https://gitee.com/yadong.zhang/JustAuth/pulls/3), 解决抖音登录失败问题
|
||||
|
||||
### 2019/06/18 ([v1.6.1-beta](https://gitee.com/yadong.zhang/JustAuth/releases/v1.6.1-beta))
|
||||
## v1.6.1-beta
|
||||
### 2019/06/18
|
||||
1. 解决Issue [#IY2HW](https://gitee.com/yadong.zhang/JustAuth/issues/IY2HW)
|
||||
2. 解决Issue [#IY2OH](https://gitee.com/yadong.zhang/JustAuth/issues/IY2OH)
|
||||
3. 解决Issue [#IY2FV](https://gitee.com/yadong.zhang/JustAuth/issues/IY2FV)
|
||||
@@ -96,38 +143,44 @@ qq授权登录时,需要获取`openId`作为`uuid`,在`1.6.1-beta`和`1.7.0`
|
||||
5. 解决Issue [#IY1QR](https://gitee.com/yadong.zhang/JustAuth/issues/IY1QR) 增加对Config属性的校验功能,主要校验redirect uri的合法性
|
||||
6. 合并[skqing](https://gitee.com/skqing)提交的[PR](https://gitee.com/yadong.zhang/JustAuth/pulls/2),解决一些BUG
|
||||
|
||||
### 2019/06/06 ([v1.6.0-beta](https://gitee.com/yadong.zhang/JustAuth/releases/v1.6.0-beta))
|
||||
## v1.6.0-beta
|
||||
### 2019/06/06
|
||||
1. 增加今日头条的授权登陆
|
||||
2. 发布1.6.0-beta版本,今日头条开发者暂时不能认证, 所以无法做测试,等测试通过后,正式发布release版本
|
||||
|
||||
### 2019/05/28 ([v1.5.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.5.0))
|
||||
## v1.5.0
|
||||
### 2019/05/28
|
||||
1. 增加小米账号和微软的授权登陆
|
||||
2. 发布1.5.0版本
|
||||
|
||||
### 2019/05/26 ([v1.4.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.4.0))
|
||||
## v1.4.0
|
||||
### 2019/05/26
|
||||
1. 增加抖音和Linkedin的授权登陆
|
||||
2. 修改部分图片命名
|
||||
3. 优化部分代码
|
||||
4. 修复`AuthSource`中腾讯云开发平台的拼写错误:`TENCEN_CLOUD`->`TENCENT_CLOUD`
|
||||
5. 修复支付宝登陆时用户名为空的问题
|
||||
|
||||
|
||||
### 2019/05/24 ([v1.3.3](https://gitee.com/yadong.zhang/JustAuth/releases/v1.3.3))
|
||||
## v1.3.3
|
||||
### 2019/05/24
|
||||
1. 修复一些问题
|
||||
2. 升级api,在AuthUser中增加`uuid`属性,可以通过`uuid` + `source`唯一确定一个用户,此举解决了用户身份归属的问题。
|
||||
3. 发布1.3.3版本的jar包到公开仓库(1.3.2忘记发布了,( ╯□╰ ))
|
||||
4. 重要:经咨询官方客服得知,CSDN的授权开放平台已经下线,如果以前申请过的应用,可以继续使用,但是不再支持申请新的应用。so, 本项目中的CSDN登录只能针对少部分用户使用了
|
||||
|
||||
### 2019/05/23 ([v1.3.1](https://gitee.com/yadong.zhang/JustAuth/releases/v1.3.1))
|
||||
## v1.3.1
|
||||
### 2019/05/23
|
||||
1. 修复QQ登录的问题
|
||||
2. 发布1.3.1版本的jar包到公开仓库
|
||||
|
||||
### 2019/05/21 ([v1.3.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.3.0))
|
||||
## v1.3.0
|
||||
### 2019/05/21
|
||||
1. 新增google授权登录
|
||||
2. 新增facebook授权登录
|
||||
3. 发布1.3.0版本的jar包到公开仓库
|
||||
|
||||
### 2019/05/18 ([v1.1.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.1.0) | [v1.2.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.2.0))
|
||||
## v1.1.0
|
||||
### 2019/05/18
|
||||
1. 发布1.1.0版本的jar包到公开仓库(支持qq和微信登录)
|
||||
2. 支持淘宝登录
|
||||
3. 修改`AuthUser.java`类中的`accessToken`属性,由原本的~~accessToken (String)~~改为`token (AuthToken)`
|
||||
@@ -138,8 +191,10 @@ qq授权登录时,需要获取`openId`作为`uuid`,在`1.6.1-beta`和`1.7.0`
|
||||
1. 增加qq和微信的授权登录
|
||||
2. 修改getAccessToken方法的返回值
|
||||
|
||||
### 2019/03/27 ([v1.0.1](https://gitee.com/yadong.zhang/JustAuth/releases/v1.0.1))
|
||||
## v1.0.1
|
||||
### 2019/03/27
|
||||
集成 支付宝授权登录
|
||||
|
||||
### 2019/03/25 ([v1.0.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.0.0))
|
||||
史上最全的整合第三方登录的工具,目前已支持Github、Gitee、微博、钉钉和百度、Coding、腾讯云开发者平台和OSChina登录。 Login, so easy!
|
||||
## v1.0.0
|
||||
### 2019/03/25
|
||||
史上最全的整合第三方登录的工具,目前已支持Github、Gitee、微博、钉钉和百度、Coding、腾讯云开发者平台和OSChina登录。 Login, so easy!
|
||||
@@ -0,0 +1,11 @@
|
||||
# Who is using?
|
||||
|
||||
- [spring-boot-demo](https://github.com/xkcoding/spring-boot-demo): spring boot demo 是一个用来学习 spring boot 的项目,总共包含 55 个集成demo,已经完成 46 个。(注:[spring-boot-demo-social](https://github.com/xkcoding/spring-boot-demo/tree/master/spring-boot-demo-social)模块中集成了JustAuth)注:该作者是JustAuth的开发者之一,负责开发QQ登录、微信登录、小米登录、微软登录、谷歌登录。
|
||||
- [Guns](https://gitee.com/stylefeng/guns): Guns基于Spring Boot2,致力于做更简洁的后台管理系统。(注:Guns企业版中使用到了JustAuth实现第三方OAuth登录)
|
||||
|
||||
- [Shiro-Action](https://github.com/zhaojun1998/Shiro-Action): 基于 Shiro 的权限管理系统,支持 restful url 授权
|
||||
- [project-template](https://github.com/HobbyBear/project-template): 作为前后端分离项目的后端模板整个项目基于springboot2.1.3,集jsr303框架做参数校验,spring security 做权限管理,并实现限制同一账号登陆会话数量功能,spring mail 发送邮件,justAuth做的第三方登陆, spring session做session共享,orm框架采用jpa,集成七牛云实现图片上传,redis实现分布式锁
|
||||
- [mica](https://github.com/lets-mica/mica/tree/master/mica-social):mica是Spring Cloud 微服务开发核心包。采用源码形式(保留了作者名)另加改了一些代码。
|
||||
...
|
||||
|
||||
我在这儿等你 >>> :alien:
|
||||
@@ -0,0 +1,3 @@
|
||||
# 使用State
|
||||
|
||||
待补充
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<version>1.10.1</version>
|
||||
|
||||
<name>JustAuth</name>
|
||||
<url>https://gitee.com/yadong.zhang/JustAuth</url>
|
||||
@@ -52,14 +52,18 @@
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven-source.version>2.2.1</maven-source.version>
|
||||
<maven-compiler.version>3.7.0</maven-compiler.version>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
<maven-compiler.version>3.8.1</maven-compiler.version>
|
||||
<maven-javadoc.version>3.1.0</maven-javadoc.version>
|
||||
<cobertura-version>2.7</cobertura-version>
|
||||
<maven-surefire-version>2.20</maven-surefire-version>
|
||||
<maven-gpg-version>1.6</maven-gpg-version>
|
||||
<maven.test.skip>false</maven.test.skip>
|
||||
<hutool-version>4.6.1</hutool-version>
|
||||
<lombok-version>1.18.4</lombok-version>
|
||||
<junit-version>4.11</junit-version>
|
||||
<fastjson-version>1.2.58</fastjson-version>
|
||||
<alipay-sdk-version>3.7.4.ALL</alipay-sdk-version>
|
||||
<slf4j-version>1.7.25</slf4j-version>
|
||||
<jacoco-version>0.8.2</jacoco-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -91,11 +95,6 @@
|
||||
<version>${alipay-sdk-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -112,6 +111,7 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>${maven-source.version}</version>
|
||||
<inherited>true</inherited>
|
||||
@@ -127,10 +127,30 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven-javadoc.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-version}</version>
|
||||
<configuration>
|
||||
<!-- 包含其他测试类 -->
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
<!-- 排除掉AuthRequestTest测试类,该类只做api演示用 -->
|
||||
<excludes>
|
||||
<exclude>**/AuthRequestTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
@@ -154,13 +174,32 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>${cobertura-version}</version>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
<check/>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>${jacoco-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -168,6 +207,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>${maven-gpg-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
@@ -190,5 +230,36 @@
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
<!--私服-->
|
||||
<profile>
|
||||
<id>nexus</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>${maven-gpg-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>xkcoding-nexus</id>
|
||||
<url>https://nexus.xkcoding.com/repository/maven-releases/</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>xkcoding-nexus</id>
|
||||
<url>https://nexus.xkcoding.com/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package me.zhyd.oauth.cache;
|
||||
|
||||
/**
|
||||
* AuthCache配置类
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthCacheConfig {
|
||||
|
||||
/**
|
||||
* 默认缓存过期时间:3分钟
|
||||
* 鉴于授权过程中,根据个人的操作习惯,或者授权平台的不同(google等),每个授权流程的耗时也有差异,不过单个授权流程一般不会太长
|
||||
* 本缓存工具默认的过期时间设置为3分钟,即程序默认认为3分钟内的授权有效,超过3分钟则默认失效,失效后删除
|
||||
*/
|
||||
public static long timeout = 3 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* 是否开启定时{@link AuthDefaultCache#pruneCache()}的任务
|
||||
*/
|
||||
public static boolean schedulePrune = true;
|
||||
}
|
||||
@@ -13,6 +13,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public enum AuthCacheScheduler {
|
||||
|
||||
/**
|
||||
* 当前实例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private AtomicInteger cacheTaskNumber = new AtomicInteger(1);
|
||||
|
||||
+4
-8
@@ -18,12 +18,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
*/
|
||||
public class AuthDefaultCache implements AuthCache {
|
||||
|
||||
/**
|
||||
* 默认缓存过期时间:3分钟
|
||||
* 鉴于授权过程中,根据个人的操作习惯,或者授权平台的不同(google等),每个授权流程的耗时也有差异,不过单个授权流程一般不会太长
|
||||
* 本缓存工具默认的过期时间设置为3分钟,即程序默认认为3分钟内的授权有效,超过3分钟则默认失效,失效后删除
|
||||
*/
|
||||
private static final long DEF_TIMEOUT = 3 * 60 * 1000;
|
||||
/**
|
||||
* state cache
|
||||
*/
|
||||
@@ -33,7 +27,9 @@ public class AuthDefaultCache implements AuthCache {
|
||||
private final Lock readLock = cacheLock.readLock();
|
||||
|
||||
public AuthDefaultCache() {
|
||||
this.schedulePrune(DEF_TIMEOUT);
|
||||
if (AuthCacheConfig.schedulePrune) {
|
||||
this.schedulePrune(AuthCacheConfig.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +40,7 @@ public class AuthDefaultCache implements AuthCache {
|
||||
*/
|
||||
@Override
|
||||
public void set(String key, String value) {
|
||||
set(key, value, DEF_TIMEOUT);
|
||||
set(key, value, AuthCacheConfig.timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package me.zhyd.oauth.cache;
|
||||
|
||||
/**
|
||||
* 默认的state缓存实现
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public enum AuthDefaultStateCache implements AuthStateCache {
|
||||
|
||||
/**
|
||||
* 当前实例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private AuthCache authCache;
|
||||
|
||||
AuthDefaultStateCache() {
|
||||
authCache = new AuthDefaultCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value) {
|
||||
authCache.set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
* @param timeout 指定缓存过期时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value, long timeout) {
|
||||
authCache.set(key, value, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存内容
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return authCache.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在key,如果对应key的value值已过期,也返回false
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return true:存在key,并且value没过期;false:key不存在或者已过期
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
return authCache.containsKey(key);
|
||||
}
|
||||
}
|
||||
+11
-18
@@ -1,22 +1,21 @@
|
||||
package me.zhyd.oauth.cache;
|
||||
|
||||
/**
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @since 1.8
|
||||
* <p>
|
||||
* State缓存接口,方便用户扩展
|
||||
* </p>
|
||||
*
|
||||
* @author yangkai.shen
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthStateCache {
|
||||
private static AuthCache authCache = new AuthDefaultCache();
|
||||
|
||||
public interface AuthStateCache {
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
*/
|
||||
public static void cache(String key, String value) {
|
||||
authCache.set(key, value);
|
||||
}
|
||||
void cache(String key, String value);
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
@@ -25,9 +24,7 @@ public class AuthStateCache {
|
||||
* @param value 缓存内容
|
||||
* @param timeout 指定缓存过期时间(毫秒)
|
||||
*/
|
||||
public static void cache(String key, String value, long timeout) {
|
||||
authCache.set(key, value, timeout);
|
||||
}
|
||||
void cache(String key, String value, long timeout);
|
||||
|
||||
/**
|
||||
* 获取缓存内容
|
||||
@@ -35,9 +32,7 @@ public class AuthStateCache {
|
||||
* @param key 缓存key
|
||||
* @return 缓存内容
|
||||
*/
|
||||
public static String get(String key) {
|
||||
return authCache.get(key);
|
||||
}
|
||||
String get(String key);
|
||||
|
||||
/**
|
||||
* 是否存在key,如果对应key的value值已过期,也返回false
|
||||
@@ -45,7 +40,5 @@ public class AuthStateCache {
|
||||
* @param key 缓存key
|
||||
* @return true:存在key,并且value没过期;false:key不存在或者已过期
|
||||
*/
|
||||
public static boolean containsKey(String key) {
|
||||
return authCache.containsKey(key);
|
||||
}
|
||||
boolean containsKey(String key);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* JustAuth 缓存实现, 提供基础的基于ConcurrentHashMap + ScheduledExecutorService 实现的定时缓存。
|
||||
* 同时对外暴露{@code AuthStateCache}接口,可进行对缓存实现的自定义。
|
||||
*/
|
||||
package me.zhyd.oauth.cache;
|
||||
@@ -47,7 +47,15 @@ public class AuthConfig {
|
||||
/**
|
||||
* Stack Overflow Key
|
||||
* <p>
|
||||
* 1.9.0版本新增参数
|
||||
*
|
||||
* @since 1.9.0
|
||||
*/
|
||||
private String stackOverflowKey;
|
||||
|
||||
/**
|
||||
* 企业微信,授权方的网页应用ID
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String agentId;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package me.zhyd.oauth.config;
|
||||
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
|
||||
/**
|
||||
* 各api需要的url, 用枚举类分平台类型管理
|
||||
@@ -518,6 +518,55 @@ public enum AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.stackexchange.com/2.2/me";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 华为
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
HUAWEI {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://oauth-login.cloud.huawei.com/oauth2/v2/authorize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://api.vmall.com/rest.php";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String refresh() {
|
||||
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 企业微信
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
WECHAT_ENTERPRISE {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://open.work.weixin.qq.com/wwopen/sso/qrConnect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* JustAuth 核心配置相关,包括{@code AuthConfig}和{@code AuthSource}
|
||||
*/
|
||||
package me.zhyd.oauth.config;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 提供一些必要的枚举类
|
||||
*/
|
||||
package me.zhyd.oauth.enums;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* JustAuth专用异常封装
|
||||
*/
|
||||
package me.zhyd.oauth.exception;
|
||||
@@ -0,0 +1,150 @@
|
||||
package me.zhyd.oauth.log;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 针对JustAuth提供的轻量级的日志打印工具
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @see Log#debug(String)
|
||||
* @see Log#debug(String, Throwable)
|
||||
* @see Log#warn(String)
|
||||
* @see Log#warn(String, Throwable)
|
||||
* @see Log#error(String)
|
||||
* @see Log#error(String, Throwable)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class Log {
|
||||
|
||||
public static void debug(String msg) {
|
||||
debug(msg, null);
|
||||
}
|
||||
|
||||
public static void warn(String msg) {
|
||||
warn(msg, null);
|
||||
}
|
||||
|
||||
public static void error(String msg) {
|
||||
error(msg, null);
|
||||
}
|
||||
|
||||
public static void debug(String msg, Throwable t) {
|
||||
print(Level.DEBUG, msg, t, System.out);
|
||||
}
|
||||
|
||||
public static void warn(String msg, Throwable t) {
|
||||
print(Level.WARN, msg, t, System.out);
|
||||
}
|
||||
|
||||
public static void error(String msg, Throwable t) {
|
||||
print(Level.ERROR, msg, t, System.err);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印日志内容,格式:2019-08-02 20:44:07 main me.zhyd.oauth.log.Log(debug:39) [DEBUG] - xxxx
|
||||
*
|
||||
* @param level 日志级别
|
||||
* @param msg 日志内容
|
||||
* @param t 异常信息
|
||||
* @param ps 实际执行打印的PrintStream
|
||||
*/
|
||||
private static void print(Level level, String msg, Throwable t, PrintStream ps) {
|
||||
if (Config.enable) {
|
||||
if (level.getLevelNum() >= Config.level.getLevelNum()) {
|
||||
ps.println(String.format("%s %s %s [%s] - %s", getDate(), Thread.currentThread().getName(), getCaller(), level, msg));
|
||||
writeThrowable(t, ps);
|
||||
ps.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调用方的信息
|
||||
*
|
||||
* @return 返回调用方的信息,格式:class(method:lineNumber)
|
||||
*/
|
||||
private static String getCaller() {
|
||||
int offset = 2;
|
||||
StackTraceElement[] stackTraceArr = (new Throwable()).getStackTrace();
|
||||
StackTraceElement stackTrace = null;
|
||||
if (offset >= stackTraceArr.length) {
|
||||
offset = offset - 1;
|
||||
}
|
||||
stackTrace = stackTraceArr[offset];
|
||||
return stackTrace.getClassName() +
|
||||
"(" +
|
||||
stackTrace.getMethodName() +
|
||||
':' +
|
||||
stackTrace.getLineNumber() +
|
||||
")";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取格式化后的日期
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static String getDate() {
|
||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印异常信息
|
||||
*
|
||||
* @param t 异常
|
||||
* @param targetStream 实际执行打印的PrintStream
|
||||
*/
|
||||
private static void writeThrowable(Throwable t, PrintStream targetStream) {
|
||||
if (t != null) {
|
||||
t.printStackTrace(targetStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志级别
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Level {
|
||||
/**
|
||||
* DEBUG: 普通级别
|
||||
*/
|
||||
DEBUG(10),
|
||||
/**
|
||||
* WARN: 警告级别
|
||||
*/
|
||||
WARN(30),
|
||||
/**
|
||||
* ERROR: 异常级别
|
||||
*/
|
||||
ERROR(40);
|
||||
|
||||
private int levelNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志配置
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
static class Config {
|
||||
|
||||
/**
|
||||
* 需要打印的日志级别
|
||||
*/
|
||||
static Level level = Level.DEBUG;
|
||||
/**
|
||||
* 是否启用日志打印功能,默认启用
|
||||
*/
|
||||
static boolean enable = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 针对JustAuth简单封装的日志打印工具,可用过{@link me.zhyd.oauth.log.Log.Config}开关日志和指定日志级别
|
||||
*/
|
||||
package me.zhyd.oauth.log;
|
||||
@@ -27,4 +27,11 @@ public class AuthCallback {
|
||||
* 访问AuthorizeUrl后回调时带的参数state,用于和请求AuthorizeUrl前的state比较,防止CSRF攻击
|
||||
*/
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 华为授权登录接受code的参数名
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String authorization_code;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.zhyd.oauth.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -36,4 +35,11 @@ public class AuthToken {
|
||||
private String macAlgorithm;
|
||||
private String macKey;
|
||||
|
||||
/**
|
||||
* 企业微信附带属性
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String code;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package me.zhyd.oauth.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.*;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
|
||||
@@ -15,6 +13,8 @@ import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AuthUser {
|
||||
/**
|
||||
* 用户第三方系统的唯一id。在调用方集成改组件时,可以用uuid + source唯一确定一个用户
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* JustAuth核心模型类,封装了用户、token、响应和callback等实体类
|
||||
*/
|
||||
package me.zhyd.oauth.model;
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* JustAuth,如你所见,它仅仅是一个第三方授权登录的工具类库,它可以让我们脱离繁琐的第三方登录SDK,让登录变得So easy!
|
||||
* <p>
|
||||
* 史上最全的整合第三方登录的开源库。目前已支持Github、Gitee、微博、钉钉、百度、Coding、腾讯云开发者平台、OSChina、
|
||||
* 支付宝、QQ、微信、淘宝、Google、Facebook、抖音、领英、小米、微软、今日头条、Teambition、StackOverflow、Pinterest、
|
||||
* 人人、华为和企业微信等第三方平台的授权登录。 Login, so easy!
|
||||
*/
|
||||
package me.zhyd.oauth;
|
||||
@@ -7,6 +7,7 @@ import com.alipay.api.request.AlipaySystemOauthTokenRequest;
|
||||
import com.alipay.api.request.AlipayUserInfoShareRequest;
|
||||
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
|
||||
import com.alipay.api.response.AlipayUserInfoShareResponse;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -33,6 +34,12 @@ public class AuthAlipayRequest extends AuthDefaultRequest {
|
||||
.getAlipayPublicKey(), "RSA2");
|
||||
}
|
||||
|
||||
public AuthAlipayRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.ALIPAY, authStateCache);
|
||||
this.alipayClient = new DefaultAlipayClient(AuthSource.ALIPAY.accessToken(), config.getClientId(), config.getClientSecret(), "json", "UTF-8", config
|
||||
.getAlipayPublicKey(), "RSA2");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
|
||||
|
||||
@@ -3,12 +3,16 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
@@ -24,6 +28,10 @@ public class AuthBaiduRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.BAIDU);
|
||||
}
|
||||
|
||||
public AuthBaiduRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.BAIDU, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -23,6 +24,10 @@ public class AuthCodingRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.CODING);
|
||||
}
|
||||
|
||||
public AuthCodingRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.CODING, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -23,6 +24,10 @@ public class AuthCsdnRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.CSDN);
|
||||
}
|
||||
|
||||
public AuthCsdnRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.CSDN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,12 +2,13 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.cache.AuthDefaultStateCache;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.log.Log;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
@@ -24,14 +25,19 @@ import me.zhyd.oauth.utils.UuidUtils;
|
||||
* @author yangkai.shen (https://xkcoding.com)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
protected AuthConfig config;
|
||||
protected AuthSource source;
|
||||
protected AuthStateCache authStateCache;
|
||||
|
||||
public AuthDefaultRequest(AuthConfig config, AuthSource source) {
|
||||
this(config, source, AuthDefaultStateCache.INSTANCE);
|
||||
}
|
||||
|
||||
public AuthDefaultRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) {
|
||||
this.config = config;
|
||||
this.source = source;
|
||||
this.authStateCache = authStateCache;
|
||||
if (!AuthChecker.isSupportedAuth(config, source)) {
|
||||
throw new AuthException(AuthResponseStatus.PARAMETER_INCOMPLETE);
|
||||
}
|
||||
@@ -68,14 +74,14 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
@Override
|
||||
public AuthResponse login(AuthCallback authCallback) {
|
||||
try {
|
||||
AuthChecker.checkCode(source == AuthSource.ALIPAY ? authCallback.getAuth_code() : authCallback.getCode());
|
||||
AuthChecker.checkState(authCallback.getState());
|
||||
AuthChecker.checkCode(source, authCallback);
|
||||
this.checkState(authCallback.getState());
|
||||
|
||||
AuthToken authToken = this.getAccessToken(authCallback);
|
||||
AuthUser user = this.getUserInfo(authToken);
|
||||
return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(user).build();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to login with oauth authorization.", e);
|
||||
Log.error("Failed to login with oauth authorization.", e);
|
||||
return this.responseError(e);
|
||||
}
|
||||
}
|
||||
@@ -189,7 +195,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
state = UuidUtils.getUUID();
|
||||
}
|
||||
// 缓存state
|
||||
AuthStateCache.cache(state, state);
|
||||
authStateCache.cache(state, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -254,4 +260,16 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
protected HttpResponse doGetRevoke(AuthToken authToken) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -26,6 +27,10 @@ public class AuthDingTalkRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.DINGTALK);
|
||||
}
|
||||
|
||||
public AuthDingTalkRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.DINGTALK, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return AuthToken.builder().accessCode(authCallback.getCode()).build();
|
||||
|
||||
@@ -3,12 +3,16 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
|
||||
@@ -24,6 +28,10 @@ public class AuthDouyinRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.DOUYIN);
|
||||
}
|
||||
|
||||
public AuthDouyinRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.DOUYIN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return this.getToken(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -23,6 +24,10 @@ public class AuthFacebookRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.FACEBOOK);
|
||||
}
|
||||
|
||||
public AuthFacebookRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.FACEBOOK, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -22,6 +23,10 @@ public class AuthGiteeRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.GITEE);
|
||||
}
|
||||
|
||||
public AuthGiteeRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.GITEE, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -25,6 +26,10 @@ public class AuthGithubRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.GITHUB);
|
||||
}
|
||||
|
||||
public AuthGithubRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.GITHUB, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -24,6 +25,10 @@ public class AuthGoogleRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.GOOGLE);
|
||||
}
|
||||
|
||||
public AuthGoogleRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.GOOGLE, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import static me.zhyd.oauth.enums.AuthResponseStatus.SUCCESS;
|
||||
|
||||
/**
|
||||
* 华为授权登录
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthHuaweiRequest extends AuthDefaultRequest {
|
||||
|
||||
public AuthHuaweiRequest(AuthConfig config) {
|
||||
super(config, AuthSource.HUAWEI);
|
||||
}
|
||||
|
||||
public AuthHuaweiRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.HUAWEI, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取access token
|
||||
*
|
||||
* @param authCallback 授权成功后的回调参数
|
||||
* @return token
|
||||
* @see AuthDefaultRequest#authorize()
|
||||
* @see AuthDefaultRequest#authorize(String)
|
||||
*/
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpRequest request = HttpRequest.post(source.accessToken())
|
||||
.form("grant_type", "authorization_code")
|
||||
.form("code", authCallback.getAuthorization_code())
|
||||
.form("client_id", config.getClientId())
|
||||
.form("client_secret", config.getClientSecret())
|
||||
.form("redirect_uri", config.getRedirectUri());
|
||||
return getAuthToken(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用token换取用户信息
|
||||
*
|
||||
* @param authToken token信息
|
||||
* @return 用户信息
|
||||
* @see AuthDefaultRequest#getAccessToken(AuthCallback)
|
||||
*/
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpResponse response = HttpRequest.post(source.userInfo())
|
||||
.form("nsp_ts", System.currentTimeMillis())
|
||||
.form("access_token", authToken.getAccessToken())
|
||||
.form("nsp_fmt", "JS")
|
||||
.form("nsp_svc", "OpenUP.User.getInfo")
|
||||
.execute();
|
||||
JSONObject object = JSONObject.parseObject(response.body());
|
||||
|
||||
this.checkResponse(object);
|
||||
|
||||
AuthUserGender gender = getRealGender(object);
|
||||
|
||||
return AuthUser.builder()
|
||||
.uuid(object.getString("userID"))
|
||||
.username(object.getString("userName"))
|
||||
.nickname(object.getString("userName"))
|
||||
.gender(gender)
|
||||
.avatar(object.getString("headPictureURL"))
|
||||
.token(authToken)
|
||||
.source(source)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新access token (续期)
|
||||
*
|
||||
* @param authToken 登录成功后返回的Token信息
|
||||
* @return AuthResponse
|
||||
*/
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
HttpRequest request = HttpRequest.post(source.refresh())
|
||||
.form("client_id", config.getClientId())
|
||||
.form("client_secret", config.getClientSecret())
|
||||
.form("refresh_token", authToken.getRefreshToken())
|
||||
.form("grant_type", "refresh_token");
|
||||
return AuthResponse.builder()
|
||||
.code(SUCCESS.getCode())
|
||||
.data(getAuthToken(request))
|
||||
.build();
|
||||
}
|
||||
|
||||
private AuthToken getAuthToken(HttpRequest request) {
|
||||
HttpResponse response = request.execute();
|
||||
JSONObject object = JSONObject.parseObject(response.body());
|
||||
|
||||
this.checkResponse(object);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(object.getString("access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.refreshToken(object.getString("refresh_token"))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
* @since 1.9.3
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("access_type", "offline")
|
||||
.queryParam("scope", "https%3A%2F%2Fwww.huawei.com%2Fauth%2Faccount%2Fbase.profile")
|
||||
.queryParam("state", getRealState(state))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权码
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.queryParam("grant_type", "authorization_code")
|
||||
.queryParam("code", code)
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("client_secret", config.getClientSecret())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取userInfo的url
|
||||
*
|
||||
* @param authToken token
|
||||
* @return 返回获取userInfo的url
|
||||
*/
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("nsp_ts", System.currentTimeMillis())
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("nsp_fmt", "JS")
|
||||
.queryParam("nsp_svc", "OpenUP.User.getInfo")
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的实际性别。华为系统中,用户的性别:1表示女,0表示男
|
||||
*
|
||||
* @param object obj
|
||||
* @return AuthUserGender
|
||||
*/
|
||||
private AuthUserGender getRealGender(JSONObject object) {
|
||||
int genderCodeInt = object.getIntValue("gender");
|
||||
String genderCode = genderCodeInt == 1 ? "0" : (genderCodeInt == 0) ? "1" : genderCodeInt + "";
|
||||
return AuthUserGender.getRealGender(genderCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验响应结果
|
||||
*
|
||||
* @param object 接口返回的结果
|
||||
*/
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("NSP_STATUS")) {
|
||||
throw new AuthException(object.getString("error"));
|
||||
}
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("sub_error") + ":" + object.getString("error_description"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,16 @@ import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONPath;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
@@ -27,6 +31,10 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.LINKEDIN);
|
||||
}
|
||||
|
||||
public AuthLinkedinRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.LINKEDIN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return this.getToken(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
@@ -4,13 +4,17 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.log.Log;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
@@ -21,7 +25,6 @@ import java.text.MessageFormat;
|
||||
* @author yangkai.shen (https://xkcoding.com)
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class AuthMiRequest extends AuthDefaultRequest {
|
||||
private static final String PREFIX = "&&&START&&&";
|
||||
|
||||
@@ -29,6 +32,10 @@ public class AuthMiRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.MI);
|
||||
}
|
||||
|
||||
public AuthMiRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.MI, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return getToken(accessTokenUrl(authCallback.getCode()));
|
||||
@@ -88,7 +95,7 @@ public class AuthMiRequest extends AuthDefaultRequest {
|
||||
JSONObject emailPhone = userEmailPhone.getJSONObject("data");
|
||||
authUser.setEmail(emailPhone.getString("email"));
|
||||
} else {
|
||||
log.warn("小米开发平台暂时不对外开放用户手机及邮箱信息的获取");
|
||||
Log.warn("小米开发平台暂时不对外开放用户手机及邮箱信息的获取");
|
||||
}
|
||||
|
||||
return authUser;
|
||||
|
||||
@@ -3,12 +3,16 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import static me.zhyd.oauth.utils.GlobalAuthUtil.parseQueryToMap;
|
||||
@@ -24,6 +28,10 @@ public class AuthMicrosoftRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.MICROSOFT);
|
||||
}
|
||||
|
||||
public AuthMicrosoftRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.MICROSOFT, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return getToken(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -23,6 +24,10 @@ public class AuthOschinaRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.OSCHINA);
|
||||
}
|
||||
|
||||
public AuthOschinaRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.OSCHINA, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
@@ -29,6 +30,10 @@ public class AuthPinterestRequest extends AuthDefaultRequest {
|
||||
super(config, PINTEREST);
|
||||
}
|
||||
|
||||
public AuthPinterestRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, PINTEREST, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -4,12 +4,16 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtil;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
@@ -28,6 +32,10 @@ public class AuthQqRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.QQ);
|
||||
}
|
||||
|
||||
public AuthQqRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.QQ, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(authCallback.getCode());
|
||||
@@ -37,10 +45,7 @@ public class AuthQqRequest extends AuthDefaultRequest {
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
HttpResponse response = HttpRequest.get(refreshTokenUrl(authToken.getRefreshToken())).execute();
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(getAuthToken(response))
|
||||
.build();
|
||||
return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(getAuthToken(response)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,10 +4,14 @@ import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -27,6 +31,10 @@ public class AuthRenrenRequest extends AuthDefaultRequest {
|
||||
super(config, RENREN);
|
||||
}
|
||||
|
||||
public AuthRenrenRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, RENREN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return this.getToken(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
|
||||
/**
|
||||
* JustAuth {@code Request}公共接口,所有平台的{@code Request}都需要实现该接口
|
||||
* <p>
|
||||
* {@link AuthRequest#authorize()}
|
||||
* {@link AuthRequest#authorize(String)}
|
||||
* {@link AuthRequest#login(AuthCallback)}
|
||||
* {@link AuthRequest#revoke(AuthToken)}
|
||||
* {@link AuthRequest#refresh(AuthToken)}
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.8
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
@@ -26,6 +27,10 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest {
|
||||
super(config, STACK_OVERFLOW);
|
||||
}
|
||||
|
||||
public AuthStackOverflowRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, STACK_OVERFLOW, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
String accessTokenUrl = accessTokenUrl(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -24,6 +25,10 @@ public class AuthTaobaoRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.TAOBAO);
|
||||
}
|
||||
|
||||
public AuthTaobaoRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.TAOBAO, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return AuthToken.builder().accessCode(authCallback.getCode()).build();
|
||||
|
||||
@@ -3,12 +3,16 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
|
||||
/**
|
||||
* Teambition授权登录
|
||||
@@ -22,6 +26,10 @@ public class AuthTeambitionRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.TEAMBITION);
|
||||
}
|
||||
|
||||
public AuthTeambitionRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.TEAMBITION, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authCallback 回调返回的参数
|
||||
* @return 所有信息
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -23,6 +24,10 @@ public class AuthTencentCloudRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.TENCENT_CLOUD);
|
||||
}
|
||||
|
||||
public AuthTencentCloudRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.TENCENT_CLOUD, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthToutiaoErrorCode;
|
||||
@@ -24,6 +25,10 @@ public class AuthToutiaoRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.TOUTIAO);
|
||||
}
|
||||
|
||||
public AuthToutiaoRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.TOUTIAO, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(authCallback.getCode());
|
||||
@@ -119,8 +124,7 @@ public class AuthToutiaoRequest extends AuthDefaultRequest {
|
||||
*/
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("error_code")) {
|
||||
throw new AuthException(AuthToutiaoErrorCode.getErrorCode(object.getIntValue("error_code"))
|
||||
.getDesc());
|
||||
throw new AuthException(AuthToutiaoErrorCode.getErrorCode(object.getIntValue("error_code")).getDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 企业微信登录
|
||||
* </p>
|
||||
*
|
||||
* @author yangkai.shen (https://xkcoding.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthWeChatEnterpriseRequest extends AuthDefaultRequest {
|
||||
public AuthWeChatEnterpriseRequest(AuthConfig config) {
|
||||
super(config, AuthSource.WECHAT_ENTERPRISE);
|
||||
}
|
||||
|
||||
public AuthWeChatEnterpriseRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.WECHAT_ENTERPRISE, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
|
||||
*
|
||||
* @param authCallback 回调返回的参数
|
||||
* @return 所有信息
|
||||
*/
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(object.getString("access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.code(authCallback.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpResponse response = doGetUserInfo(authToken);
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
// 返回 OpenId 或其他,均代表非当前企业用户,不支持
|
||||
if (!object.containsKey("UserId")) {
|
||||
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM);
|
||||
}
|
||||
String userId = object.getString("UserId");
|
||||
HttpResponse userDetailResponse = getUserDetail(authToken.getAccessToken(), userId);
|
||||
JSONObject userDetail = this.checkResponse(userDetailResponse);
|
||||
|
||||
String gender = getRealGender(userDetail);
|
||||
|
||||
return AuthUser.builder()
|
||||
.username(userDetail.getString("name"))
|
||||
.nickname(userDetail.getString("alias"))
|
||||
.avatar(userDetail.getString("avatar"))
|
||||
.location(userDetail.getString("address"))
|
||||
.email(userDetail.getString("email"))
|
||||
.uuid(userId)
|
||||
.gender(AuthUserGender.getRealGender(gender))
|
||||
.token(authToken)
|
||||
.source(source)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验请求结果
|
||||
*
|
||||
* @param response 请求结果
|
||||
* @return 如果请求结果正常,则返回JSONObject
|
||||
*/
|
||||
private JSONObject checkResponse(HttpResponse response) {
|
||||
JSONObject object = JSONObject.parseObject(response.body());
|
||||
|
||||
if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
|
||||
throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的实际性别,0表示未定义,1表示男性,2表示女性
|
||||
*
|
||||
* @param userDetail 用户详情
|
||||
* @return 用户性别
|
||||
*/
|
||||
private String getRealGender(JSONObject userDetail) {
|
||||
int gender = userDetail.getIntValue("gender");
|
||||
if (AuthUserGender.MALE.getCode() == gender) {
|
||||
return "1";
|
||||
}
|
||||
return 2 == gender ? "0" : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
* @since 1.9.3
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("appid", config.getClientId())
|
||||
.queryParam("agentid", config.getAgentId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("state", getRealState(state))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权码
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.queryParam("corpid", config.getClientId())
|
||||
.queryParam("corpsecret", config.getClientSecret())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取userInfo的url
|
||||
*
|
||||
* @param authToken 用户授权后的token
|
||||
* @return 返回获取userInfo的url
|
||||
*/
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("code", authToken.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户详情
|
||||
*
|
||||
* @param accessToken accessToken
|
||||
* @param userId 企业内用户id
|
||||
* @return 用户详情
|
||||
*/
|
||||
private HttpResponse getUserDetail(String accessToken, String userId) {
|
||||
String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
|
||||
.queryParam("access_token", accessToken)
|
||||
.queryParam("userid", userId)
|
||||
.build();
|
||||
return HttpRequest.get(userDetailUrl).execute();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,12 +3,16 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.*;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
@@ -22,6 +26,10 @@ public class AuthWeChatRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.WECHAT);
|
||||
}
|
||||
|
||||
public AuthWeChatRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.WECHAT, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.zhyd.oauth.request;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -27,6 +28,10 @@ public class AuthWeiboRequest extends AuthDefaultRequest {
|
||||
super(config, AuthSource.WEIBO);
|
||||
}
|
||||
|
||||
public AuthWeiboRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.WEIBO, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doPostAuthorizationCode(authCallback.getCode());
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* JustAuth核心组件,所有授权登录都是基于{@code request}实现
|
||||
*/
|
||||
package me.zhyd.oauth.request;
|
||||
@@ -1,10 +1,10 @@
|
||||
package me.zhyd.oauth.utils;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
|
||||
/**
|
||||
* 授权配置类的校验器
|
||||
@@ -30,6 +30,9 @@ public class AuthChecker {
|
||||
if (isSupported && AuthSource.STACK_OVERFLOW == source) {
|
||||
isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
|
||||
}
|
||||
if (isSupported && AuthSource.WECHAT_ENTERPRISE == source){
|
||||
isSupported = StringUtils.isNotEmpty(config.getAgentId());
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
@@ -57,24 +60,22 @@ public class AuthChecker {
|
||||
|
||||
/**
|
||||
* 校验回调传回的code
|
||||
* <p>
|
||||
* {@code v1.10.0}版本中改为传入{@code source}和{@code callback},对于不同平台使用不同参数接受code的情况统一做处理
|
||||
*
|
||||
* @param code 回调时传回的code
|
||||
* @param source 当前授权平台
|
||||
* @param callback 从第三方授权回调回来时传入的参数集合
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public static void checkCode(String code) {
|
||||
public static void checkCode(AuthSource source, AuthCallback callback) {
|
||||
String code = callback.getCode();
|
||||
if (source == AuthSource.ALIPAY) {
|
||||
code = callback.getAuth_code();
|
||||
} else if (source == AuthSource.HUAWEI) {
|
||||
code = callback.getAuthorization_code();
|
||||
}
|
||||
if (StringUtils.isEmpty(code)) {
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验回调传回的state
|
||||
*
|
||||
* @param state {@code state}一定不为空
|
||||
*/
|
||||
public static void checkState(String state) {
|
||||
if (StringUtils.isEmpty(state) || !AuthStateCache.containsKey(state)) {
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 提供一些简单的工具和校验等
|
||||
*/
|
||||
package me.zhyd.oauth.utils;
|
||||
@@ -16,7 +16,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -30,7 +30,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthGithubRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -44,7 +44,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthWeiboRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -58,7 +58,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthDingTalkRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -72,7 +72,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthBaiduRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -86,7 +86,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthCodingRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -100,7 +100,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthTencentCloudRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -114,7 +114,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthOschinaRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -128,7 +128,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthAlipayRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.alipayPublicKey("publicKey")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
@@ -143,7 +143,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthQqRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -157,7 +157,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthWeChatRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -171,7 +171,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthTaobaoRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -185,7 +185,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthGoogleRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -199,7 +199,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthFacebookRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("https://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -213,7 +213,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthDouyinRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -227,7 +227,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthLinkedinRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -241,7 +241,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthMicrosoftRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -255,7 +255,7 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthMiRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
@@ -269,7 +269,36 @@ public class AuthRequestTest {
|
||||
AuthRequest authRequest = new AuthToutiaoRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参
|
||||
// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
|
||||
AuthResponse login = authRequest.login(new AuthCallback());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void huaweiTest() {
|
||||
AuthRequest authRequest = new AuthHuaweiRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("http://redirectUri")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的入参
|
||||
// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
|
||||
AuthResponse login = authRequest.login(new AuthCallback());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void weChatEnterpriseTest() {
|
||||
AuthRequest authRequest = new AuthWeChatEnterpriseRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("http://redirectUri")
|
||||
.agentId("agentId")
|
||||
.build());
|
||||
// 返回授权页面,可自行跳转
|
||||
authRequest.authorize("state");
|
||||
|
||||
@@ -9,24 +9,24 @@ public class AuthStateCacheTest {
|
||||
|
||||
@Test
|
||||
public void cache1() throws InterruptedException {
|
||||
AuthStateCache.cache("key", "value");
|
||||
Assert.assertEquals(AuthStateCache.get("key"), "value");
|
||||
AuthDefaultStateCache.INSTANCE.cache("key", "value");
|
||||
Assert.assertEquals(AuthDefaultStateCache.INSTANCE.get("key"), "value");
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(4);
|
||||
Assert.assertEquals(AuthStateCache.get("key"), "value");
|
||||
Assert.assertEquals(AuthDefaultStateCache.INSTANCE.get("key"), "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cache2() throws InterruptedException {
|
||||
AuthStateCache.cache("key", "value", 10);
|
||||
Assert.assertEquals(AuthStateCache.get("key"), "value");
|
||||
AuthDefaultStateCache.INSTANCE.cache("key", "value", 10);
|
||||
Assert.assertEquals(AuthDefaultStateCache.INSTANCE.get("key"), "value");
|
||||
|
||||
// 没过期
|
||||
TimeUnit.MILLISECONDS.sleep(5);
|
||||
Assert.assertEquals(AuthStateCache.get("key"), "value");
|
||||
Assert.assertEquals(AuthDefaultStateCache.INSTANCE.get("key"), "value");
|
||||
|
||||
// 过期
|
||||
TimeUnit.MILLISECONDS.sleep(6);
|
||||
Assert.assertNull(AuthStateCache.get("key"));
|
||||
Assert.assertNull(AuthDefaultStateCache.INSTANCE.get("key"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package me.zhyd.oauth.log;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @date 2019/8/2 19:36
|
||||
* @since 1.8
|
||||
*/
|
||||
public class LogTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 测试正常打印
|
||||
Log.debug("[1] This is a test.");
|
||||
Log.debug("[1] This is a test.", new NullPointerException("npe"));
|
||||
|
||||
Log.warn("[1] This is a test.");
|
||||
Log.warn("[1] This is a test.", new NullPointerException("npe"));
|
||||
|
||||
Log.error("[1] This is a test.");
|
||||
Log.error("[1] This is a test.", new NullPointerException("npe"));
|
||||
|
||||
// 测试只打印 error级别的日志
|
||||
Log.Config.level = Log.Level.ERROR;
|
||||
|
||||
Log.debug("[2] This is a test.");
|
||||
Log.warn("[2] This is a test.");
|
||||
Log.error("[2] This is a test.");
|
||||
|
||||
// 测试关闭日志
|
||||
Log.Config.enable = false;
|
||||
|
||||
Log.debug("[3] This is a test.");
|
||||
Log.warn("[3] This is a test.");
|
||||
Log.error("[3] This is a test.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 1000000: 23135ms
|
||||
* 100000: 3016ms
|
||||
* 10000: 328ms
|
||||
* 1000: 26ms
|
||||
*/
|
||||
@Test
|
||||
public void testByThread() {
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < 1; i++) {
|
||||
System.out.println(callMethodByThread());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println((end - start) + "ms");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 1000000: 19058ms
|
||||
* 100000: 2772ms
|
||||
* 10000: 323ms
|
||||
* 1000: 29ms
|
||||
*/
|
||||
@Test
|
||||
public void testByThrowable() {
|
||||
long end = System.currentTimeMillis();
|
||||
for (int i = 0; i < 1; i++) {
|
||||
System.out.println(callMethodByThrowable());
|
||||
}
|
||||
long end2 = System.currentTimeMillis();
|
||||
System.out.println((end2 - end) + "ms");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBySecurityManager() {
|
||||
long end = System.currentTimeMillis();
|
||||
for (int i = 0; i < 1; i++) {
|
||||
System.out.println(callMethodBySecurityManager());
|
||||
}
|
||||
long end2 = System.currentTimeMillis();
|
||||
System.out.println((end2 - end) + "ms");
|
||||
|
||||
}
|
||||
|
||||
private String callMethodByThread() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
System.out.println(stackTraceElement.getMethodName());
|
||||
}
|
||||
return stackTrace[2].getMethodName();
|
||||
}
|
||||
|
||||
private String callMethodByThrowable() {
|
||||
StackTraceElement[] stackTrace = (new Throwable()).getStackTrace();
|
||||
for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
System.out.println(stackTraceElement.getMethodName());
|
||||
}
|
||||
return stackTrace[2].getMethodName();
|
||||
}
|
||||
|
||||
private String callMethodBySecurityManager() {
|
||||
return new SecurityManager() {
|
||||
String getClassName() {
|
||||
for (Class clazz : getClassContext()) {
|
||||
System.out.println(clazz);
|
||||
}
|
||||
return getClassContext()[0].getName();
|
||||
}
|
||||
}.getClassName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package me.zhyd.oauth.model;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AuthUserTest {
|
||||
|
||||
@Test
|
||||
public void serialize() {
|
||||
|
||||
AuthUser user = AuthUser.builder()
|
||||
.nickname("test")
|
||||
.build();
|
||||
String json = JSON.toJSONString(user);
|
||||
Assert.assertEquals(json, "{\"nickname\":\"test\"}");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserialize() {
|
||||
AuthUser user = AuthUser.builder()
|
||||
.nickname("test")
|
||||
.build();
|
||||
String json = JSON.toJSONString(user);
|
||||
|
||||
AuthUser deserializeUser = JSON.parseObject(json, AuthUser.class);
|
||||
Assert.assertEquals(deserializeUser.getNickname(), "test");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package me.zhyd.oauth.sdk;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class ThirdPartSdkTest {
|
||||
|
||||
@Test
|
||||
public void huawei() {
|
||||
String code = "CF1IwmFc6uZABI9Y795BkhXfvHidIFFw04I4Zc4KML4n+vlXxwNUcQKS4xlopjFDpEk6LzQbjwdTNxvjZ9jqnd/1m5nswhx8X7e0/dL2kyGAMVZWFgVq9ClxNN18b+Z0xtfJjkm7bDnfC3W5h4COgTCoLSjiWKSHWp5hCunp6pQRo1FHovZXm13TLNlhF9mCVtJx3kTQ";
|
||||
HttpResponse response = HttpRequest.post("https://oauth-login.cloud.huawei.com/oauth2/v2/token")
|
||||
.form("grant_type", "authorization_code")
|
||||
.form("code", code)
|
||||
.form("client_id", "100994535")
|
||||
.form("client_secret", "22aea400bef603fef26d15a79c806eb477b35de0a529758f2a3b1bda32bfb80d")
|
||||
.form("redirect_uri", "http://127.0.0.1:8443/oauth/callback/huawei")
|
||||
.execute();
|
||||
System.out.println(response.body());
|
||||
|
||||
// {"access_token":"accessToken","expires_in":3600,"refresh_token":"refreshToken","scope":"https:\/\/www.huawei.com\/auth\/account\/base.profile","token_type":"Bearer"}
|
||||
|
||||
//
|
||||
HttpResponse response2 = HttpRequest.post("https://api.vmall.com/rest.php")
|
||||
.form("nsp_ts", System.currentTimeMillis())
|
||||
.form("access_token", JSONObject.parseObject(response.body()).getString("access_token"))
|
||||
.form("nsp_fmt", "JS")
|
||||
// .form("nsp_cb", "_jqjsp")
|
||||
.form("nsp_svc", "OpenUP.User.getInfo")
|
||||
.execute();
|
||||
System.out.println(response2.body());
|
||||
// 华为性别 0是男,女是1
|
||||
// {"gender":1,"headPictureURL":"https://upfile-drcn.platform.hicloud.com/FileServer/image/b.0260086000226601572.20190415065228.iBKdTsqaNkdPXSz4N7pIRWAgeu45ec3k.1000.9A5467309F9284B267ECA33B59D3D7DA4A71BC732D3BB24EC6B880A73DEE9BAB.jpg","languageCode":"zh-CN","userID":"260086000226601572","userName":"151****2326","userState":1,"userValidStatus":1}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package me.zhyd.oauth.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONPath;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 其他测试方法
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
*/
|
||||
public class CustomTest {
|
||||
|
||||
/**
|
||||
* 1000000: 23135ms
|
||||
* 100000: 3016ms
|
||||
* 10000: 328ms
|
||||
* 1000: 26ms
|
||||
*/
|
||||
@Test
|
||||
public void test() {
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
callMethod();
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println((end - start) + "ms");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 1000000: 19058ms
|
||||
* 100000: 2772ms
|
||||
* 10000: 323ms
|
||||
* 1000: 29ms
|
||||
*/
|
||||
@Test
|
||||
public void test2() {
|
||||
long end = System.currentTimeMillis();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
callMethod2();
|
||||
}
|
||||
long end2 = System.currentTimeMillis();
|
||||
System.out.println((end2 - end) + "ms");
|
||||
|
||||
}
|
||||
|
||||
public String callMethod() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
// for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
// System.out.println(stackTraceElement.getMethodName());
|
||||
// }
|
||||
return stackTrace[2].getMethodName();
|
||||
}
|
||||
|
||||
public String callMethod2() {
|
||||
StackTraceElement[] stackTrace = (new Throwable()).getStackTrace();
|
||||
// for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
// System.out.println(stackTraceElement.getMethodName());
|
||||
// }
|
||||
return stackTrace[2].getMethodName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonpath() {
|
||||
List<Map<String, Map<String, Object>>> list = new ArrayList<>();
|
||||
|
||||
Map<String, Map<String, Object>> map = new HashMap<>();
|
||||
Map<String, Object> node = new HashMap<>();
|
||||
node.put("emailAddress", "xxxx");
|
||||
map.put("handle~", node);
|
||||
list.add(map);
|
||||
|
||||
|
||||
Map<String, Object> master = new HashMap<>();
|
||||
// master.put("elements", list);
|
||||
JSONObject emailObj = JSONObject.parseObject(JSON.toJSONString(master));
|
||||
Object object = JSONPath.eval(emailObj, "$['elements'][0]['handle~']['emailAddress']");
|
||||
System.out.println(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package me.zhyd.oauth.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONPath;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JsonPath用法测试
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
*/
|
||||
public class JsonPathTest {
|
||||
|
||||
@Test
|
||||
public void jsonPath() {
|
||||
List<Map<String, Map<String, Object>>> list = new ArrayList<>();
|
||||
|
||||
Map<String, Map<String, Object>> map = new HashMap<>();
|
||||
Map<String, Object> node = new HashMap<>();
|
||||
node.put("emailAddress", "xxxx");
|
||||
map.put("handle~", node);
|
||||
list.add(map);
|
||||
|
||||
|
||||
Map<String, Object> master = new HashMap<>();
|
||||
// master.put("elements", list);
|
||||
JSONObject emailObj = JSONObject.parseObject(JSON.toJSONString(master));
|
||||
Object object = JSONPath.eval(emailObj, "$['elements'][0]['handle~']['emailAddress']");
|
||||
System.out.println(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package me.zhyd.oauth.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class StringUtilsTest {
|
||||
@Rule
|
||||
public final ExpectedException thrown =
|
||||
ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void isEmptyNonEmptyInput() {
|
||||
Assert.assertFalse(StringUtils.isEmpty("non-empty string"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEmptyEmptyInput() {
|
||||
Assert.assertTrue(StringUtils.isEmpty(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEmptyInputNull() {
|
||||
Assert.assertTrue(StringUtils.isEmpty(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEmptyNonEmptyInput() {
|
||||
Assert.assertTrue(StringUtils.isNotEmpty("non-empty string"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEmptyEmptyInput() {
|
||||
Assert.assertFalse(StringUtils.isNotEmpty(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEmptyInputNull() {
|
||||
Assert.assertFalse(StringUtils.isNotEmpty(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIfNotContainAppendedStringNotPresent() {
|
||||
// (Check the case where appendStr doesn't occur in str)
|
||||
final String str = "Prefix ";
|
||||
final String appendStr = "suffix";
|
||||
final String otherwise = "should be discarded";
|
||||
|
||||
final String result =
|
||||
StringUtils.appendIfNotContain(str, appendStr, otherwise);
|
||||
|
||||
Assert.assertEquals("Prefix suffix", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIfNotContainAppendedStringPresent() {
|
||||
// (Check the case where appendStr occurs in str)
|
||||
final String str = "Prefix ";
|
||||
final String appendStr = "Prefix";
|
||||
final String otherwise = "should be appended";
|
||||
|
||||
final String result =
|
||||
StringUtils.appendIfNotContain(str, appendStr, otherwise);
|
||||
|
||||
Assert.assertEquals("Prefix should be appended", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIfNotContainEmptyString() {
|
||||
// (Check the special-case for str being empty)
|
||||
final String str = "";
|
||||
final String appendStr = "should not be appended";
|
||||
final String otherwise = "should also not be appended";
|
||||
|
||||
final String result =
|
||||
StringUtils.appendIfNotContain(str, appendStr, otherwise);
|
||||
|
||||
Assert.assertEquals("", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIfNotContainAppendingEmptyString() {
|
||||
// (Check the special-case for appendStr being empty)
|
||||
final String str = "should be kept";
|
||||
final String appendStr = "";
|
||||
final String otherwise = "should also not be appended";
|
||||
|
||||
final String result =
|
||||
StringUtils.appendIfNotContain(str, appendStr, otherwise);
|
||||
|
||||
Assert.assertEquals("should be kept", result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user