Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b758e0e1e | |||
| 02bd057963 | |||
| 4d2a110fea | |||
| 2ef8298278 | |||
| 80ce57bce4 | |||
| 2fed3e5ba2 | |||
| 1d38ce2835 | |||
| 14dd2b6179 | |||
| d6ba3bba10 | |||
| fe328c7375 | |||
| 102521a979 | |||
| 924f0f552b | |||
| 7167a74af2 | |||
| c0ac81df08 | |||
| 56cdd20600 | |||
| 87d8c1d164 | |||
| d1f820514f | |||
| 6d192e94ac | |||
| 02bec576de | |||
| 0d599d75f0 | |||
| 5171fb8148 | |||
| 0025748ba7 | |||
| 87cf45b675 | |||
| bd1192f17f | |||
| a7cb4aefc0 | |||
| 7ffda8737c | |||
| 90a9d56fd0 | |||
| c53c763540 | |||
| dc18304eee | |||
| a558379680 | |||
| 142846b2fa | |||
| 80b59fc13c | |||
| 765127e847 | |||
| 11707e6903 | |||
| 3564c846f4 | |||
| 0bc4c806bf | |||
| 35c754f327 | |||
| 45ebe26f1b | |||
| 30f4a29f48 | |||
| ca8e194c4e | |||
| 81ea4b1620 | |||
| cc74d4a5c8 | |||
| e80304601f | |||
| afddf269e1 | |||
| bac494a7fc | |||
| 7a9d602499 | |||
| f3a8cf675c | |||
| 571466f079 | |||
| e1b912bdf6 | |||
| 02674049d0 | |||
| f1714726f5 | |||
| a3108caccf | |||
| e134dd06b0 | |||
| 172ba7be55 | |||
| f9e3053ecc | |||
| 99c9ba2854 | |||
| 544ffd5372 | |||
| 522ebbfa7f | |||
| 497498dbf4 | |||
| 62cd7af619 | |||
| 3a3f69692c | |||
| c87015e34f | |||
| 96773dd92d | |||
| 644ef02264 | |||
| 4c205a9957 | |||
| ea70c5fc81 | |||
| 9ced525309 | |||
| 2de0ad5013 | |||
| 23b7bcf43d | |||
| 976b7d8b2b | |||
| 80132b69e7 | |||
| 95158654a9 | |||
| f2e609192a | |||
| 8c8f7a27a2 | |||
| 8283124c57 | |||
| 39b113b194 | |||
| e45ef2ec31 | |||
| d114368a0d | |||
| 0047cde50e | |||
| f2c1c0f8a6 | |||
| 21e23aadb9 | |||
| db3f7da181 | |||
| 004e5a180f | |||
| 50c31e5dea | |||
| 7d6049da67 | |||
| 9a24553acd | |||
| d75d91db0d | |||
| e1a4688ac0 | |||
| b1d3790ae1 | |||
| e5548b0173 | |||
| ebf39627dd | |||
| 74ee17b242 | |||
| b77de0bd0c | |||
| e55033f4f5 | |||
| 37b7784f89 | |||
| 7cdc719166 | |||
| 5073f82897 | |||
| 9971793f0c | |||
| 9fc3131640 | |||
| 3f4436bcb6 | |||
| 0678202baa |
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://www.justauth.cn/sponsor.html']
|
||||
@@ -9,8 +9,8 @@ assignees: ''
|
||||
## Pre-submission checklist:
|
||||
|
||||
- [ ] I have searched the relevant information in the existing list of Issues.
|
||||
- [ ] I have searched the developer documentation for that information: https://justauth.wiki
|
||||
- [ ] I have read the relevant Q&A: https://justauth.wiki
|
||||
- [ ] I have searched the developer documentation for that information: https://www.justauth.cn
|
||||
- [ ] I have read the relevant Q&A: https://www.justauth.cn
|
||||
|
||||
## Issue description
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
paths:
|
||||
- src/**
|
||||
- pom.xml
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
- name: Set up Java and Maven
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'zulu'
|
||||
- name: Cache m2 package
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- run: mvn test
|
||||
|
||||
deploy-snapshot:
|
||||
needs: test
|
||||
if: ${{ success() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
- name: Set up Java and Maven
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'zulu'
|
||||
server-id: ossrh
|
||||
server-username: MAVEN_USERNAME
|
||||
server-password: MAVEN_PASSWORD
|
||||
- name: Cache m2 package
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- name: setting snapshot version
|
||||
run: |
|
||||
import xml.etree.ElementTree as ET
|
||||
tree = ET.parse("pom.xml")
|
||||
version = tree.find("{http://maven.apache.org/POM/4.0.0}version")
|
||||
print(version.text + "-SNAPSHOT")
|
||||
if version.text.endswith("-SNAPSHOT") == False:
|
||||
tree.find("{http://maven.apache.org/POM/4.0.0}version").text = version.text + "-SNAPSHOT"
|
||||
ET.register_namespace("", "http://maven.apache.org/POM/4.0.0")
|
||||
tree.write("pom.xml", "utf-8", True)
|
||||
shell: python
|
||||
- name: deploy snapshot to ossrh repository
|
||||
run: mvn -B deploy -P snapshot -DskipTests
|
||||
env:
|
||||
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
|
||||
@@ -0,0 +1,26 @@
|
||||
name: test pull_request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- src/**
|
||||
- pom.xml
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.2.0
|
||||
- name: Set up Java and Maven
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'zulu'
|
||||
- name: Cache m2 package
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- run: mvn test
|
||||
@@ -28,8 +28,6 @@ hs_err_pid*
|
||||
bin/codecov.sh
|
||||
bin/deploy.sh
|
||||
bin/docsify-cli.sh
|
||||
bin/push.sh
|
||||
bin/push-dev.sh
|
||||
|
||||
target
|
||||
/pom.xml.versionsBackup
|
||||
|
||||
@@ -1,3 +1,64 @@
|
||||
## 1.16.6
|
||||
|
||||
### 2023/12/03
|
||||
- 优化
|
||||
- 微信公众平台支持返回快照标识(快照标识为 true 时,标识当前获取到的微信用户信息都是虚拟的)
|
||||
- 企业微信网页登录--获取用户敏感信。 [Github #155](https://github.com/justauth/JustAuth/pull/155)
|
||||
- 添加飞书单元测试。 [Github #159](https://github.com/justauth/JustAuth/pull/159)
|
||||
- 升级fastjson版本到1.2.83,1.2.83版本之前存在代码执行漏洞风险 ,CVE-2022-25845。[Gitee PR #31](https://gitee.com/yadong.zhang/JustAuth/pulls/31)
|
||||
- 新增
|
||||
- 添加微软中国(世纪华联)第三方登录,新增微软方式登录的redirectUri校验。[Gitee PR #33](https://gitee.com/yadong.zhang/JustAuth/pulls/33)
|
||||
- 新增爱发电平台 [Gitee #35](https://gitee.com/yadong.zhang/JustAuth/pulls/35)
|
||||
- 微软平台适配 AzureAD(目前改名为 Microsoft Entra ID)登录认证
|
||||
- Fixed
|
||||
- 修复 twitter 平台在 Java11 环境下登录失败的问题。[#174](https://github.com/justauth/JustAuth/issues/174)
|
||||
- 修复 Facebook 平台无法登录的问题(facebook 平台 API 进行了升级)
|
||||
- 修复微信公众平台 scope 为 snsapi_base 登录报错的问题 [181](https://github.com/justauth/JustAuth/issues/181)
|
||||
|
||||
## 1.16.5
|
||||
|
||||
### 2021/10/18
|
||||
|
||||
- 合并 PR [Github #138](https://github.com/justauth/JustAuth/pull/138)
|
||||
- 升级alipay-sdk-version的依赖版本
|
||||
- 修改用户logo的尺寸
|
||||
- 修复 alipay 登录失败的 BUG [Gitee Issue #I4E4ML](https://gitee.com/yadong.zhang/JustAuth/issues/I4E4ML)
|
||||
|
||||
|
||||
## 1.16.4
|
||||
|
||||
### 2021/9/22
|
||||
|
||||
- 合并 PR
|
||||
- [Github #134](https://github.com/justauth/JustAuth/pull/134)
|
||||
- [Github #133](https://github.com/justauth/JustAuth/pull/133)
|
||||
- [Github #132](https://github.com/justauth/JustAuth/pull/132)
|
||||
- [Github #131](https://github.com/justauth/JustAuth/pull/131)
|
||||
- 添加微软中国(世纪华联)第三方登录,新增微软方式登录的redirectUri校验。[Gitee PR #28](https://gitee.com/yadong.zhang/JustAuth/pulls/28)
|
||||
- 升级第三方的依赖
|
||||
- simple-http > 1.0.5
|
||||
- lombok > 1.18.20
|
||||
- junit > 4.13.2
|
||||
- fastjson > 1.2.78
|
||||
- alipay-sdk > 4.16.38.ALL
|
||||
|
||||
## 1.16.3
|
||||
|
||||
### 2021/8/15
|
||||
|
||||
- 发布 v1.16.3
|
||||
- 新增
|
||||
- 集成“企业微信的第三方应用”平台登录
|
||||
- PR
|
||||
- `AuthRequst` 增加 `Builder` 构建方式,使用起来更简单。 ([#27](https://gitee.com/yadong.zhang/JustAuth/pulls/27))
|
||||
- 使用 Github Action 添加发布快照的 workflow。 ([#126](https://github.com/justauth/JustAuth/pull/126))
|
||||
- 新增了企业微信的第三方应用登录,`AuthWeChatEnterpriseThirdQrcodeRequest`。 ([#127](https://github.com/justauth/JustAuth/pull/127))
|
||||
- 添加快照版本对应更详细的文档。 ([#128](https://github.com/justauth/JustAuth/pull/128))
|
||||
- 修改
|
||||
- 在 Gitee PR ([#27](https://gitee.com/yadong.zhang/JustAuth/pulls/27)) 的基础上重构代码,增加 Builder 方式创建 AuthRequest
|
||||
- 解决 Line 登录的错误。[#122](https://github.com/justauth/JustAuth/issues/122)
|
||||
|
||||
|
||||
## 1.16.2
|
||||
|
||||
### 2021/7/28
|
||||
@@ -117,7 +178,7 @@
|
||||
- 新增 [微信企业版登录](oauth/wechatEnterprise.md)文档
|
||||
- 新增 [Facebook 登录](oauth/facebook.md)文档
|
||||
- 完善 [JustAuth 使用者](users.md)文档
|
||||
- 替换“帮助文档”域名,由[https://docs.justauth.whnb.wang](https://docs.justauth.whnb.wang)迁移到[https://justauth.wiki](https://justauth.wiki)
|
||||
- 替换“帮助文档”域名,由[https://docs.justauth.whnb.wang](https://docs.justauth.whnb.wang)迁移到[https://www.justauth.cn](https://www.justauth.cn)
|
||||
- 新增
|
||||
- 增加阿里云授权登录中刷新授权token的接口,by “QQ群用户需求”
|
||||
- AuthConfig 增加忽略校验 state 的参数,详情参考:[Github#Issue#83](https://github.com/justauth/JustAuth/issues/83)
|
||||
@@ -170,7 +231,7 @@ new AuthGoogleRequest(AuthConfig.builder()
|
||||
- 修复
|
||||
- 解决 Twitter 授权失败的BUG
|
||||
- 文档
|
||||
- 完善 [https://justauth.wiki](https://justauth.wiki/) 的404引导页内容
|
||||
- 完善 [https://www.justauth.cn](https://www.justauth.cn/) 的404引导页内容
|
||||
- 增加名词解释: `uuid`
|
||||
- 补充 [Q&A](Q&A.md)
|
||||
- 新增 [参考文档](references.md),包含 OAuth 授权和第三方平台的API文档等内容
|
||||
@@ -250,9 +311,9 @@ System.setProperty("proxyHost", "127.0.0.1");
|
||||
- 新增
|
||||
- 增加微信、QQ、支付宝、微博授权登录的帮助文档
|
||||
- 合并[PR#57](https://github.com/justauth/JustAuth/pull/57),增加微信公众号登录 by [@xkcoding](https://github.com/xkcoding)
|
||||
- [帮助文档](https://justauth.wiki)中增加自定义的404页面
|
||||
- [帮助文档](https://justauth.wiki)中增加Gittalk插件
|
||||
- [帮助文档](https://justauth.wiki)中增加Java代码高亮的插件
|
||||
- [帮助文档](https://www.justauth.cn)中增加自定义的404页面
|
||||
- [帮助文档](https://www.justauth.cn)中增加Gittalk插件
|
||||
- [帮助文档](https://www.justauth.cn)中增加Java代码高亮的插件
|
||||
- 增加`AuthUserGender#getWechatRealGender`方法,兼容获取微信平台的用户性别
|
||||
- 修改
|
||||
- 修复抖音登录取值取错层级的问题([issue#I15SIG@Gitee](https://gitee.com/yadong.zhang/JustAuth/issues/I15SIG))
|
||||
@@ -261,7 +322,7 @@ System.setProperty("proxyHost", "127.0.0.1");
|
||||
- `AuthResponseStatus`枚举类中增加`ILLEGAL_STATUS`、`REQUIRED_REFRESH_TOKEN`两个枚举值
|
||||
- `AuthSource`接口中增加`getName`方法,用来对外提供实际`source`的字符串值
|
||||
- `AuthWeiboRequest`微博授权登录中实现`revoke`方法,支持手动回收授权
|
||||
- [帮助文档](https://justauth.wiki)中修复[腾讯云登录]链接错误的问题
|
||||
- [帮助文档](https://www.justauth.cn)中修复[腾讯云登录]链接错误的问题
|
||||
- 升级
|
||||
- 升级相关依赖:lombok@v1.18.10,hutool@5.0.5,fastjson@1.2.62,alipay@4.8.10.ALL([PR#11@Gitee](https://gitee.com/yadong.zhang/JustAuth/pulls/11))
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="https://justauth.wiki"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/Justauth.png" width="400"></a>
|
||||
<a href="https://www.justauth.cn"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/Justauth.png" width="400"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>Login, so easy.</strong>
|
||||
@@ -8,13 +8,16 @@
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/github/v/release/justauth/JustAuth?style=flat-square" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://oss.sonatype.org/content/repositories/snapshots/me/zhyd/oauth/JustAuth/">
|
||||
<img src="https://img.shields.io/nexus/s/https/oss.sonatype.org/me.zhyd.oauth/JustAuth.svg?style=flat-square" ></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://justauth.wiki" title="参考文档">
|
||||
<a target="_blank" href="https://www.justauth.cn" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/justauth/JustAuth">
|
||||
@@ -40,7 +43,7 @@
|
||||
`JustAuth`, as you see, It is just a Java library of third-party authorized login, It's smaller and easier to use. JustAuth is the best third-party login tool written in JAVA.
|
||||
|
||||
Source Code:[gitee](https://gitee.com/yadong.zhang/JustAuth) | [github](https://github.com/zhangyd-c/JustAuth)
|
||||
Docs:[Reference Doc](https://justauth.wiki)
|
||||
Docs:[Reference Doc](https://www.justauth.cn)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -49,34 +52,28 @@ Docs:[Reference Doc](https://justauth.wiki)
|
||||
|
||||
## Quick start
|
||||
|
||||
- Add maven dependency
|
||||
### Add maven dependency
|
||||
|
||||
- Add JustAuth dependency
|
||||
|
||||
These artifacts are available from Maven Central:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.2</version>
|
||||
<version>{latest-version}</version>
|
||||
</dependency>
|
||||
```
|
||||
- Using JustAuth
|
||||
```java
|
||||
// Create authorization request
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build());
|
||||
// Generate authorization url
|
||||
authRequest.authorize("state");
|
||||
// After authorization to login, it will return: code(auth_code(Alipay only)),state, After version 1.8.0, you can use the AuthCallback as a parameter to the callback interface
|
||||
// Note: JustAuth saves state for 3 minutes by default. If it is not used within 3 minutes, the expired state will be cleared automatically.
|
||||
authRequest.login(callback);
|
||||
```
|
||||
|
||||
Note, that since [v1.14.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.14.0) JustAuth has been integrated by default with [simple-http](https://github.com/xkcoding/simple-http) as the HTTP general interface (see the update [JustAuth 1.14.0 release! Perfect decoupling of HTTP tools](https://mp.weixin.qq.com/s?__biz=MzA3NDk3OTIwMg==&mid=2450633197&idx=1&sn=11e625b307db62b2f1c4e82f7744b2a2&chksm=88929300bfe51a16562b45592a264482ae2c74c6dbfa4a3aa9611ad4fea4a9be5b1f0545527d&token=1093833287&lang=zh_CN#rd)). Since most projects already integrate HTTP tools such as OkHttp3, apache HttpClient, and hutool-http), in order to reduce unnecessary dependencies,Starting from [v1.14.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.14.0), JustAuth will not integrate hutool-http by default. If the developer's project is new or there is no integrated HTTP implementation tool in the project, please add the corresponding HTTP implementation class by yourself. Alternative dependencies are as follows:
|
||||
> **latest-version** :
|
||||
> - CURRENT: 
|
||||
> - SNAPSHOT: 
|
||||
|
||||
|
||||
- Add http dependency(Only need one)
|
||||
|
||||
> If there is already in the project, please ignore it. In addition, you need to pay special attention. If the low version of the dependency has been introduced in the project, please exclude the low version of the dependency first, and then introduce the high version or the latest version of the dependency
|
||||
|
||||
- hutool-http
|
||||
|
||||
```xml
|
||||
@@ -107,6 +104,68 @@ Note, that since [v1.14.0](https://gitee.com/yadong.zhang/JustAuth/releases/v1.1
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
### Using JustAuth API
|
||||
|
||||
#### Simple
|
||||
|
||||
```java
|
||||
// Create authorization request
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build());
|
||||
// Generate authorization page url
|
||||
authRequest.authorize("state");
|
||||
// Get token and userinfo
|
||||
authRequest.login(callback);
|
||||
```
|
||||
|
||||
#### Builder 1. Use unchanging `AuthConfig`
|
||||
|
||||
```java
|
||||
// Create authorization request
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("github")
|
||||
.authConfig(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build())
|
||||
.build();
|
||||
```
|
||||
|
||||
#### Builder 2. Use dynamic `AuthConfig`
|
||||
|
||||
```java
|
||||
// Create authorization request
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("gitee")
|
||||
.authConfig((source) -> {
|
||||
// Use source to dynamically get AuthConfig
|
||||
// Here you can flexibly take the configuration from sql or take the configuration from the configuration file
|
||||
return AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build();
|
||||
})
|
||||
.build();
|
||||
```
|
||||
|
||||
#### Builder 3. Support custom platform
|
||||
|
||||
```java
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
// Key point: configure the custom implementation of AuthSource
|
||||
.extendSource(AuthExtendSource.values())
|
||||
// Enum name in AuthExtendSource
|
||||
.source("other")
|
||||
// ... Do other things
|
||||
.build();
|
||||
```
|
||||
|
||||
## Contributions
|
||||
|
||||
1. Fork this project to your repository
|
||||
@@ -121,11 +180,11 @@ I look forward to your joining us.
|
||||
|
||||
## Contributors
|
||||
|
||||
[contributors](https://justauth.wiki/contributors.html)
|
||||
[contributors](https://www.justauth.cn/contributors.html)
|
||||
|
||||
## Change Logs
|
||||
|
||||
[CHANGELOGS](https://justauth.wiki/update.html)
|
||||
[CHANGELOGS](https://www.justauth.cn/update.html)
|
||||
|
||||
## Recommend
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="https://justauth.wiki"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/Justauth.png" width="400"></a>
|
||||
<a href="https://www.justauth.cn"><img src="https://gitee.com/yadong.zhang/static/raw/master/JustAuth/Justauth.png" width="400"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>Login, so easy.</strong>
|
||||
@@ -8,13 +8,16 @@
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/github/v/release/justauth/JustAuth?style=flat-square" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://oss.sonatype.org/content/repositories/snapshots/me/zhyd/oauth/JustAuth/">
|
||||
<img src="https://img.shields.io/nexus/s/https/oss.sonatype.org/me.zhyd.oauth/JustAuth.svg?style=flat-square" ></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://justauth.wiki" title="参考文档">
|
||||
<a target="_blank" href="https://www.justauth.cn" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/justauth/JustAuth">
|
||||
@@ -37,13 +40,13 @@
|
||||
|
||||
QQ 群:230017570
|
||||
微信群:justauth (备注`justauth`或者`ja`)
|
||||
帮助文档:[justauth.wiki](https://justauth.wiki)
|
||||
帮助文档:[www.justauth.cn](https://www.justauth.cn)
|
||||
|
||||
## 什么是 JustAuth?
|
||||
|
||||
JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具类库**,它可以让我们脱离繁琐的第三方登录 SDK,让登录变得**So easy!**
|
||||
|
||||
JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、Google、Facebook、Twitter、StackOverflow等国内外数十家第三方平台。更多请参考<a href="https://justauth.wiki" target="_blank">已集成的平台</a>
|
||||
JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、Google、Facebook、Twitter、StackOverflow等国内外数十家第三方平台。更多请参考<a href="https://www.justauth.cn" target="_blank">已集成的平台</a>
|
||||
|
||||
## 有哪些特点?
|
||||
|
||||
@@ -52,24 +55,94 @@ JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、
|
||||
|
||||
## 有哪些功能?
|
||||
|
||||
- 集成国内外数十家第三方平台,实现快速接入。<a href="https://justauth.wiki/quickstart/how-to-use.html" target="_blank">参考文档</a>
|
||||
- 自定义 State 缓存,支持各种分布式缓存组件。<a href="https://justauth.wiki/features/customize-the-state-cache.html" target="_blank">参考文档</a>
|
||||
- 自定义 OAuth 平台,更容易适配自有的 OAuth 服务。<a href="https://justauth.wiki/features/customize-the-oauth.html" target="_blank">参考文档</a>
|
||||
- 自定义 Http 实现,选择权完全交给开发者,不会单独依赖某一具体实现。<a href="https://justauth.wiki/quickstart/how-to-use.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F" target="_blank">参考文档</a>
|
||||
- 自定义 Scope,支持更完善的授权体系。<a href="https://justauth.wiki/features/customize-scopes.html" target="_blank">参考文档</a>
|
||||
- 更多...<a href="https://justauth.wiki" target="_blank">参考文档</a>
|
||||
- 集成国内外数十家第三方平台,实现快速接入。<a href="https://www.justauth.cn/quickstart/how-to-use.html" target="_blank">参考文档</a>
|
||||
- 自定义 State 缓存,支持各种分布式缓存组件。<a href="https://www.justauth.cn/features/customize-the-state-cache.html" target="_blank">参考文档</a>
|
||||
- 自定义 OAuth 平台,更容易适配自有的 OAuth 服务。<a href="https://www.justauth.cn/features/customize-the-oauth.html" target="_blank">参考文档</a>
|
||||
- 自定义 Http 实现,选择权完全交给开发者,不会单独依赖某一具体实现。<a href="https://www.justauth.cn/quickstart/how-to-use.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F" target="_blank">参考文档</a>
|
||||
- 自定义 Scope,支持更完善的授权体系。<a href="https://www.justauth.cn/features/customize-scopes.html" target="_blank">参考文档</a>
|
||||
- 更多...<a href="https://www.justauth.cn" target="_blank">参考文档</a>
|
||||
|
||||
## 快速开始
|
||||
|
||||
- 引入依赖
|
||||
### 引入依赖
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.2</version>
|
||||
<version>{latest-version}</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
|
||||
> **latest-version** 可选:
|
||||
> - 稳定版:
|
||||
> - 快照版:
|
||||
> > 注意:快照版本是功能的尝鲜,并不保证稳定性。请勿在生产环境中使用。
|
||||
>
|
||||
> <details>
|
||||
> <summary>如何引入快照版本</summary>
|
||||
>
|
||||
> JustAuth 的快照版本托管在 ossrh 上,所以要指定下载地址。
|
||||
>
|
||||
> ```xml
|
||||
> <repositories>
|
||||
> <repository>
|
||||
> <id>ossrh-snapshot</id>
|
||||
> <url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
> <snapshots>
|
||||
> <enabled>true</enabled>
|
||||
> </snapshots>
|
||||
> </repository>
|
||||
> </repositories>
|
||||
> ```
|
||||
>
|
||||
> 如果你想第一时间获取 JustAuth 的最新快照,可以添加下列代码,每次构建时都检查是否有最新的快照(默认每天检查)。
|
||||
>
|
||||
> ```diff
|
||||
> <url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
> <snapshots>
|
||||
> + <updatePolicy>always</updatePolicy>
|
||||
> <enabled>true</enabled>
|
||||
> </snapshots>
|
||||
> ```
|
||||
>
|
||||
> </details>
|
||||
|
||||
如下**任选一种** HTTP 工具 依赖,_项目内如果已有,请忽略。另外需要特别注意,如果项目中已经引入了低版本的依赖,请先排除低版本依赖后,再引入高版本或者最新版本的依赖_
|
||||
|
||||
- hutool-http
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-http</artifactId>
|
||||
<version>5.7.7</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- httpclient
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- okhttp
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 调用api
|
||||
|
||||
#### 普通方式
|
||||
|
||||
```java
|
||||
// 创建授权request
|
||||
AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
|
||||
@@ -84,47 +157,72 @@ authRequest.authorize("state");
|
||||
authRequest.login(callback);
|
||||
```
|
||||
|
||||
如下**任选一种** HTTP 工具 依赖,_项目内如果已有,请忽略。另外需要特别注意,如果项目中已经引入了低版本的依赖,请先排除低版本以后来,引入高版本或者最新版本的依赖_
|
||||
#### Builder 方式一
|
||||
|
||||
- hutool-http
|
||||
静态配置 `AuthConfig`
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-http</artifactId>
|
||||
<version>5.2.5</version>
|
||||
</dependency>
|
||||
```
|
||||
```java
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("github")
|
||||
.authConfig(AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build())
|
||||
.build();
|
||||
// 生成授权页面
|
||||
authRequest.authorize("state");
|
||||
// 授权登录后会返回code(auth_code(仅限支付宝))、state,1.8.0版本后,可以用AuthCallback类作为回调接口的参数
|
||||
// 注:JustAuth默认保存state的时效为3分钟,3分钟内未使用则会自动清除过期的state
|
||||
authRequest.login(callback);
|
||||
```
|
||||
|
||||
- httpclient
|
||||
#### Builder 方式二
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.12</version>
|
||||
</dependency>
|
||||
```
|
||||
动态获取并配置 `AuthConfig`
|
||||
|
||||
- okhttp
|
||||
```java
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("gitee")
|
||||
.authConfig((source) -> {
|
||||
// 通过 source 动态获取 AuthConfig
|
||||
// 此处可以灵活的从 sql 中取配置也可以从配置文件中取配置
|
||||
return AuthConfig.builder()
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.redirectUri("redirectUri")
|
||||
.build();
|
||||
})
|
||||
.build();
|
||||
Assert.assertTrue(authRequest instanceof AuthGiteeRequest);
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
```
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.4.1</version>
|
||||
</dependency>
|
||||
```
|
||||
#### Builder 方式支持自定义的平台
|
||||
|
||||
```java
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
// 关键点:将自定义实现的 AuthSource 配置上
|
||||
.extendSource(AuthExtendSource.values())
|
||||
// source 对应 AuthExtendSource 中的枚举 name
|
||||
.source("other")
|
||||
// ... 其他内容不变,参考上面的示例
|
||||
.build();
|
||||
```
|
||||
|
||||
## 赞助和支持
|
||||
|
||||
感谢以下赞助商的支持:
|
||||
|
||||
[我要赞助](https://justauth.wiki/sponsor.html)
|
||||
[我要赞助](https://www.justauth.cn/sponsor.html)
|
||||
|
||||
## JustAuth 的用户
|
||||
有很多公司、组织和个人把 JustAuth 用于学习、研究、生产环境和商业产品中,包括(但不限于):
|
||||

|
||||
|
||||
[](https://www.mochiwang.com "给作者提供云写作的一个工具")
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
怎么没有我?[登记](https://gitee.com/yadong.zhang/JustAuth/issues/IZ2T7)
|
||||
@@ -136,7 +234,7 @@ authRequest.login(callback);
|
||||
- `mica` SpringBoot 微服务高效开发工具集: [https://github.com/lets-mica/mica](https://github.com/lets-mica/mica)
|
||||
- `sureness` 面向restful api的高性能认证鉴权框架:[sureness](https://github.com/usthe/sureness)
|
||||
|
||||
更多推荐,请参考:[JustAuth - 开源推荐](https://justauth.wiki)
|
||||
更多推荐,请参考:[JustAuth - 开源推荐](https://www.justauth.cn)
|
||||
|
||||
## 鸣谢
|
||||
|
||||
@@ -148,8 +246,8 @@ authRequest.login(callback);
|
||||
|
||||
## 其他
|
||||
|
||||
- [CONTRIBUTORS](https://justauth.wiki/contributors.html)
|
||||
- [CHANGELOGS](https://justauth.wiki/update.html)
|
||||
- [CONTRIBUTORS](https://www.justauth.cn/contributors.html)
|
||||
- [CHANGELOGS](https://www.justauth.cn/update.html)
|
||||
- [PLAN](https://gitee.com/yadong.zhang/JustAuth/issues/IUGRK)
|
||||
|
||||
## 贡献者列表
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
git pull origin dev && git pull github dev
|
||||
@@ -0,0 +1 @@
|
||||
git push origin dev && git push github dev
|
||||
@@ -0,0 +1 @@
|
||||
git push origin master && git push github master
|
||||
@@ -1 +1 @@
|
||||
1.16.2
|
||||
1.16.6
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.location.href = "https://justauth.wiki";
|
||||
window.location.href = "https://www.justauth.cn";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
Before Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
@@ -96,6 +96,10 @@ _注:非全部平台,部分平台可能不存在图例_
|
||||
|
||||

|
||||
|
||||
#### 授权afdian
|
||||
|
||||

|
||||
|
||||
#### 授权Twitter
|
||||
|
||||

|
||||
|
||||
@@ -15,6 +15,9 @@ case "$1" in
|
||||
'updv')
|
||||
bin/updVersion.sh $2
|
||||
;;
|
||||
'ppd')
|
||||
bin/pull-dev.sh
|
||||
;;
|
||||
'pd')
|
||||
bin/push-dev.sh
|
||||
;;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.2</version>
|
||||
<version>1.16.6</version>
|
||||
|
||||
<name>JustAuth</name>
|
||||
<url>https://gitee.com/yadong.zhang/JustAuth</url>
|
||||
@@ -57,11 +57,11 @@
|
||||
<maven-surefire-version>2.20</maven-surefire-version>
|
||||
<maven-gpg-version>1.6</maven-gpg-version>
|
||||
<maven.test.skip>false</maven.test.skip>
|
||||
<simple-http.version>1.0.3</simple-http.version>
|
||||
<lombok-version>1.18.10</lombok-version>
|
||||
<junit-version>4.13.1</junit-version>
|
||||
<fastjson-version>1.2.76</fastjson-version>
|
||||
<alipay-sdk-version>4.8.10.ALL</alipay-sdk-version>
|
||||
<simple-http.version>1.0.5</simple-http.version>
|
||||
<lombok-version>1.18.20</lombok-version>
|
||||
<junit-version>4.13.2</junit-version>
|
||||
<fastjson-version>1.2.83</fastjson-version>
|
||||
<alipay-sdk-version>4.17.5.ALL</alipay-sdk-version>
|
||||
<jacoco-version>0.8.2</jacoco-version>
|
||||
</properties>
|
||||
|
||||
@@ -93,6 +93,12 @@
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>${alipay-sdk-version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<groupId>com.alibaba</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -157,6 +163,15 @@
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>snapshot</id>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
@@ -222,10 +237,6 @@
|
||||
</plugins>
|
||||
</build>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package me.zhyd.oauth;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.request.AuthDefaultRequest;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 快捷的构建 AuthRequest
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @author ngcly
|
||||
* @version 1.0.0
|
||||
* @since 1.16.3
|
||||
*/
|
||||
public class AuthRequestBuilder {
|
||||
private String source;
|
||||
private AuthConfig authConfig;
|
||||
private AuthStateCache authStateCache;
|
||||
private AuthSource[] extendSource;
|
||||
|
||||
private AuthRequestBuilder() {
|
||||
|
||||
}
|
||||
|
||||
public static AuthRequestBuilder builder() {
|
||||
return new AuthRequestBuilder();
|
||||
}
|
||||
|
||||
public AuthRequestBuilder source(String source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthRequestBuilder authConfig(AuthConfig authConfig) {
|
||||
this.authConfig = authConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthRequestBuilder authConfig(Function<String, AuthConfig> authConfig) {
|
||||
this.authConfig = authConfig.apply(this.source);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthRequestBuilder authStateCache(AuthStateCache authStateCache) {
|
||||
this.authStateCache = authStateCache;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthRequestBuilder extendSource(AuthSource... extendSource) {
|
||||
this.extendSource = extendSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthRequest build() {
|
||||
if (StringUtils.isEmpty(this.source) || null == this.authConfig) {
|
||||
throw new AuthException(AuthResponseStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
// 合并 JustAuth 默认的 AuthDefaultSource 和 开发者自定义的 AuthSource
|
||||
AuthSource[] sources = this.concat(AuthDefaultSource.values(), extendSource);
|
||||
// 筛选符合条件的 AuthSource
|
||||
AuthSource source = Arrays.stream(sources).distinct()
|
||||
.filter(authSource -> authSource.getName().equalsIgnoreCase(this.source))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new AuthException(AuthResponseStatus.NOT_IMPLEMENTED));
|
||||
|
||||
Class<? extends AuthDefaultRequest> targetClass = source.getTargetClass();
|
||||
if (null == targetClass) {
|
||||
throw new AuthException(AuthResponseStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
try {
|
||||
if (this.authStateCache == null) {
|
||||
return targetClass.getDeclaredConstructor(AuthConfig.class).newInstance(this.authConfig);
|
||||
} else {
|
||||
return targetClass.getDeclaredConstructor(AuthConfig.class, AuthStateCache.class).newInstance(this.authConfig, this.authStateCache);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new AuthException(AuthResponseStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
|
||||
private AuthSource[] concat(AuthSource[] first, AuthSource[] second) {
|
||||
if (null == second || second.length == 0) {
|
||||
return first;
|
||||
}
|
||||
AuthSource[] result = new AuthSource[first.length + second.length];
|
||||
System.arraycopy(first, 0, result, 0, first.length);
|
||||
System.arraycopy(second, 0, result, first.length, second.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,10 @@ public class AuthConfig {
|
||||
/**
|
||||
* 支付宝公钥:当选择支付宝登录时,该值可用
|
||||
* 对应“RSA2(SHA256)密钥”中的“支付宝公钥”
|
||||
*
|
||||
* @deprecated 请使用AuthAlipayRequest的构造方法设置"alipayPublicKey"
|
||||
*/
|
||||
@Deprecated
|
||||
private String alipayPublicKey;
|
||||
|
||||
/**
|
||||
@@ -65,6 +68,13 @@ public class AuthConfig {
|
||||
*/
|
||||
private String agentId;
|
||||
|
||||
/**
|
||||
* 企业微信第三方授权用户类型,member|admin
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String usertype;
|
||||
|
||||
/**
|
||||
* 域名前缀。
|
||||
* <p>
|
||||
@@ -171,4 +181,9 @@ public class AuthConfig {
|
||||
public String getAuthServerId() {
|
||||
return StringUtils.isEmpty(authServerId) ? "default" : authServerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Microsoft Entra ID(原微软 AAD)中的租户 ID
|
||||
*/
|
||||
private String tenantId;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.zhyd.oauth.config;
|
||||
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.request.*;
|
||||
|
||||
/**
|
||||
* JustAuth内置的各api需要的url, 用枚举类分平台类型管理
|
||||
@@ -28,6 +29,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.github.com/user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthGithubRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 新浪微博
|
||||
@@ -52,6 +58,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String revoke() {
|
||||
return "https://api.weibo.com/oauth2/revokeoauth2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeiboRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* gitee
|
||||
@@ -71,6 +82,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://gitee.com/api/v5/user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthGiteeRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 钉钉扫码登录
|
||||
@@ -90,6 +106,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://oapi.dingtalk.com/sns/getuserinfo_bycode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthDingTalkRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 钉钉账号登录
|
||||
@@ -109,6 +130,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return DINGTALK.userInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthDingTalkAccountRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 百度
|
||||
@@ -138,6 +164,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://openapi.baidu.com/oauth/2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthBaiduRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* csdn
|
||||
@@ -157,6 +188,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.csdn.net/user/getinfo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthCsdnRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Coding,
|
||||
@@ -179,6 +215,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://%s.coding.net/api/account/current_user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthCodingRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* oschina 开源中国
|
||||
@@ -198,6 +239,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://www.oschina.net/action/openapi/user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthOschinaRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 支付宝
|
||||
@@ -217,6 +263,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://openapi.alipay.com/gateway.do";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthAlipayRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* QQ
|
||||
@@ -241,6 +292,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://graph.qq.com/oauth2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthQqRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 微信开放平台
|
||||
@@ -265,6 +321,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeChatOpenRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 微信公众平台
|
||||
@@ -289,6 +350,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeChatMpRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 淘宝
|
||||
@@ -308,6 +374,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
throw new AuthException(AuthResponseStatus.UNSUPPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthTaobaoRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Google
|
||||
@@ -327,6 +398,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://www.googleapis.com/oauth2/v3/userinfo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthGoogleRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Facebook
|
||||
@@ -334,17 +410,22 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
FACEBOOK {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://www.facebook.com/v10.0/dialog/oauth";
|
||||
return "https://www.facebook.com/v18.0/dialog/oauth";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://graph.facebook.com/v10.0/oauth/access_token";
|
||||
return "https://graph.facebook.com/v18.0/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://graph.facebook.com/v10.0/me";
|
||||
return "https://graph.facebook.com/v18.0/me";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthFacebookRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -370,6 +451,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://open.douyin.com/oauth/refresh_token/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthDouyinRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 领英
|
||||
@@ -394,6 +480,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://www.linkedin.com/oauth/v2/accessToken";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthLinkedinRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 微软
|
||||
@@ -401,12 +492,12 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
MICROSOFT {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
||||
return "https://login.microsoftonline.com/%s/oauth2/v2.0/authorize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
||||
return "https://login.microsoftonline.com/%s/oauth2/v2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -416,8 +507,40 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
|
||||
@Override
|
||||
public String refresh() {
|
||||
return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
||||
return "https://login.microsoftonline.com/%s/oauth2/v2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthMicrosoftRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 微软中国(世纪互联)
|
||||
*/
|
||||
MICROSOFT_CN {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://login.partner.microsoftonline.cn/%s/oauth2/v2.0/authorize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://login.partner.microsoftonline.cn/%s/oauth2/v2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://microsoftgraph.chinacloudapi.cn/v1.0/me";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String refresh() {
|
||||
return "https://login.partner.microsoftonline.cn/%s/oauth2/v2.0/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() { return AuthMicrosoftCnRequest.class; }
|
||||
},
|
||||
/**
|
||||
* 小米
|
||||
@@ -442,6 +565,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://account.xiaomi.com/oauth2/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthMiRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 今日头条
|
||||
@@ -461,6 +589,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://open.snssdk.com/data/user_profile";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthToutiaoRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Teambition
|
||||
@@ -485,6 +618,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.teambition.com/users/me";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthTeambitionRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -510,6 +648,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.renren.com/v2/user/get";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthRenrenRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -530,6 +673,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.pinterest.com/v1/me";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthPinterestRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -550,6 +698,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.stackexchange.com/2.2/me";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthStackOverflowRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -577,6 +730,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthHuaweiRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -599,8 +757,51 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
|
||||
}
|
||||
},
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeChatEnterpriseQrcodeRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 企业微信二维码第三方登录
|
||||
*/
|
||||
WECHAT_ENTERPRISE_QRCODE_THIRD {
|
||||
/**
|
||||
* 授权的api
|
||||
*
|
||||
* @return url
|
||||
*/
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取accessToken的api
|
||||
*
|
||||
* @return url
|
||||
*/
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息的api
|
||||
*
|
||||
* @return url
|
||||
*/
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeChatEnterpriseThirdQrcodeRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 企业微信网页登录
|
||||
*/
|
||||
@@ -619,6 +820,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthWeChatEnterpriseWebRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -646,6 +852,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://oauth.kujiale.com/oauth2/auth/token/refresh";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthKujialeRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -668,6 +879,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://gitlab.com/api/v4/user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthGitlabRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -695,6 +911,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://openapi.waimai.meituan.com/oauth/refresh_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthMeituanRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -724,6 +945,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://open-api.shop.ele.me/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthElemeRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -746,6 +972,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://api.twitter.com/1.1/account/verify_credentials.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthTwitterRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -775,6 +1006,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://open.feishu.cn/open-apis/authen/v1/refresh_access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthFeishuRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 京东
|
||||
@@ -801,6 +1037,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://open-oauth.jd.com/oauth2/refresh_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthJdRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -826,6 +1067,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://oauth.aliyun.com/v1/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthAliyunRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -851,6 +1097,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://oauth.aliyun.com/v1/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthXmlyRequest.class;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -878,6 +1129,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return "https://api.amazon.com/auth/o2/token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthAmazonRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Slack
|
||||
@@ -911,6 +1167,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String revoke() {
|
||||
return "https://slack.com/api/auth.revoke";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthSlackRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* line
|
||||
@@ -942,6 +1203,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String revoke() {
|
||||
return "https://api.line.me/oauth2/v2.1/revoke";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthLineRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Okta,
|
||||
@@ -975,6 +1241,11 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String revoke() {
|
||||
return "https://%s.okta.com/oauth2/%s/v1/revoke";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthOktaRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 程序员客栈
|
||||
@@ -996,5 +1267,35 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
public String userInfo() {
|
||||
return "https://www.proginn.com/openapi/user/basic_info";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthProginnRequest.class;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 爱发电 <a href="https://afdian.net/">爱发电</a>
|
||||
*/
|
||||
AFDIAN {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://afdian.net/oauth2/authorize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://afdian.net/api/oauth2/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthProginnRequest.class;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.zhyd.oauth.config;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.request.AuthDefaultRequest;
|
||||
|
||||
/**
|
||||
* OAuth平台的API地址的统一接口,提供以下方法:
|
||||
@@ -73,4 +74,11 @@ public interface AuthSource {
|
||||
}
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest}
|
||||
*
|
||||
* @return class
|
||||
*/
|
||||
Class<? extends AuthDefaultRequest> getTargetClass();
|
||||
}
|
||||
|
||||
@@ -17,18 +17,19 @@ public enum AuthFacebookScope implements AuthScope {
|
||||
/**
|
||||
* {@code scope} 含义,以{@code description} 为准
|
||||
*/
|
||||
EMAIL("email", "获取用户的邮箱", true),
|
||||
USER_AGE_RANGE("user_age_range", "允许应用程序访问用户的年龄范围", true),
|
||||
USER_BIRTHDAY("user_birthday", "获取用户的生日", true),
|
||||
USER_FRIENDS("user_friends", "获取用户的好友列表", true),
|
||||
USER_GENDER("user_gender", "获取用户的性别", true),
|
||||
USER_HOMETOWN("user_hometown", "获取用户的家乡信息", true),
|
||||
USER_LIKES("user_likes", "获取用户的喜欢列表", true),
|
||||
PUBLIC_PROFILE("public_profile", "权限允许应用读取用户默认的公开资料", true),
|
||||
EMAIL("email", "获取用户的邮箱", false),
|
||||
USER_AGE_RANGE("user_age_range", "允许应用程序访问用户的年龄范围", false),
|
||||
USER_BIRTHDAY("user_birthday", "获取用户的生日", false),
|
||||
USER_FRIENDS("user_friends", "获取用户的好友列表", false),
|
||||
USER_GENDER("user_gender", "获取用户的性别", false),
|
||||
USER_HOMETOWN("user_hometown", "获取用户的家乡信息", false),
|
||||
USER_LIKES("user_likes", "获取用户的喜欢列表", false),
|
||||
USER_LINK("user_link", "获取用户的个人链接", true),
|
||||
USER_LOCATION("user_location", "获取用户的位置信息", true),
|
||||
USER_PHOTOS("user_photos", "获取用户的相册信息", true),
|
||||
USER_POSTS("user_posts", "获取用户发布的内容", true),
|
||||
USER_VIDEOS("user_videos", "获取用户上传的视频信息", true),
|
||||
USER_LOCATION("user_location", "获取用户的位置信息", false),
|
||||
USER_PHOTOS("user_photos", "获取用户的相册信息", false),
|
||||
USER_POSTS("user_posts", "获取用户发布的内容", false),
|
||||
USER_VIDEOS("user_videos", "获取用户上传的视频信息", false),
|
||||
GROUPS_ACCESS_MEMBER_INFO("groups_access_member_info", "获取公开的群组成员信息", false),
|
||||
PUBLISH_TO_GROUPS("publish_to_groups", "授权您的应用程序代表某人将内容发布到组中,前提是他们已经授予您的应用程序访问权限", false),
|
||||
;
|
||||
|
||||
@@ -44,6 +44,12 @@ public class AuthToken implements Serializable {
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 微信公众号 - 网页授权的登录时可用
|
||||
*
|
||||
* 微信针对网页授权登录,增加了一个快照页的逻辑,快照页获取到的微信用户的 uid oid 和头像昵称都是虚拟的信息
|
||||
*/
|
||||
private boolean snapshotUser;
|
||||
|
||||
/**
|
||||
* Twitter附带属性
|
||||
|
||||
@@ -72,4 +72,11 @@ public class AuthUser implements Serializable {
|
||||
*/
|
||||
private JSONObject rawUserInfo;
|
||||
|
||||
/**
|
||||
* 微信公众号 - 网页授权的登录时可用
|
||||
*
|
||||
* 微信针对网页授权登录,增加了一个快照页的逻辑,快照页获取到的微信用户的 uid oid 和头像昵称都是虚拟的信息
|
||||
*/
|
||||
private boolean snapshotUser;
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class AbstractAuthDingtalkRequest extends AuthDefaultRequest {
|
||||
String code = authToken.getAccessCode();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("tmp_auth_code", code);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), param.toJSONString());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), param.toJSONString()).getBody();
|
||||
JSONObject object = JSON.parseObject(response);
|
||||
if (object.getIntValue("errcode") != 0) {
|
||||
throw new AuthException(object.getString("errmsg"));
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.xkcoding.http.support.HttpHeader;
|
||||
import com.xkcoding.http.util.MapUtil;
|
||||
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.enums.scope.AuthMicrosoftScope;
|
||||
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.AuthScopeUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微软登录抽象类,负责处理使用微软国际和微软中国账号登录第三方网站的登录方式
|
||||
*
|
||||
* @author mroldx (xzfqq5201314@gmail.com)
|
||||
* @since 1.16.4
|
||||
*/
|
||||
public abstract class AbstractAuthMicrosoftRequest extends AuthDefaultRequest {
|
||||
|
||||
public AbstractAuthMicrosoftRequest(AuthConfig config, AuthSource source) {
|
||||
super(config, source);
|
||||
}
|
||||
|
||||
|
||||
public AbstractAuthMicrosoftRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) {
|
||||
super(config, source, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return getToken(accessTokenUrl(authCallback.getCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token,适用于获取access_token和刷新token
|
||||
*
|
||||
* @param accessTokenUrl 实际请求token的地址
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
|
||||
Map<String, String> form = MapUtil.parseStringToMap(accessTokenUrl, false);
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, form, httpHeader, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查响应内容是否正确
|
||||
*
|
||||
* @param object 请求响应内容
|
||||
*/
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String token = authToken.getAccessToken();
|
||||
String tokenType = authToken.getTokenType();
|
||||
String jwt = tokenType + " " + token;
|
||||
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", jwt);
|
||||
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(object)
|
||||
.uuid(object.getString("id"))
|
||||
.username(object.getString("userPrincipalName"))
|
||||
.nickname(object.getString("displayName"))
|
||||
.location(object.getString("officeLocation"))
|
||||
.email(object.getString("mail"))
|
||||
.gender(AuthUserGender.UNKNOWN)
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新access token (续期)
|
||||
*
|
||||
* @param authToken 登录成功后返回的Token信息
|
||||
* @return AuthResponse
|
||||
*/
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(getToken(refreshTokenUrl(authToken.getRefreshToken())))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
* @since 1.9.3
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
// 兼容 Microsoft Entra ID 登录(原微软 AAD)
|
||||
// @since 1.16.6
|
||||
String tenantId = StringUtils.isEmpty(config.getTenantId()) ? "common" : config.getTenantId();
|
||||
return UrlBuilder.fromBaseUrl(String.format(source.authorize(), tenantId))
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("state", getRealState(state))
|
||||
.queryParam("response_mode", "query")
|
||||
.queryParam("scope", this.getScopes(" ", false, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权code
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
String tenantId = StringUtils.isEmpty(config.getTenantId()) ? "common" : config.getTenantId();
|
||||
return UrlBuilder.fromBaseUrl(String.format(source.accessToken(), tenantId))
|
||||
.queryParam("code", code)
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("client_secret", config.getClientSecret())
|
||||
.queryParam("grant_type", "authorization_code")
|
||||
.queryParam("scope", this.getScopes(" ", false, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.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()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param refreshToken 用户授权后的token
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String refreshTokenUrl(String refreshToken) {
|
||||
String tenantId = StringUtils.isEmpty(config.getTenantId()) ? "common" : config.getTenantId();
|
||||
return UrlBuilder.fromBaseUrl(String.format(source.refresh(), tenantId))
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("client_secret", config.getClientSecret())
|
||||
.queryParam("refresh_token", refreshToken)
|
||||
.queryParam("grant_type", "refresh_token")
|
||||
.queryParam("scope", this.getScopes(" ", false, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package me.zhyd.oauth.request;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
@@ -12,6 +11,7 @@ import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
@@ -56,8 +56,8 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
|
||||
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source);
|
||||
}
|
||||
String userId = object.getString("UserId");
|
||||
String userDetailResponse = getUserDetail(authToken.getAccessToken(), userId);
|
||||
JSONObject userDetail = this.checkResponse(userDetailResponse);
|
||||
String userTicket = object.getString("user_ticket");
|
||||
JSONObject userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket);
|
||||
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(userDetail)
|
||||
@@ -123,14 +123,31 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
|
||||
*
|
||||
* @param accessToken accessToken
|
||||
* @param userId 企业内用户id
|
||||
* @param userTicket 成员票据,用于获取用户信息或敏感信息
|
||||
* @return 用户详情
|
||||
*/
|
||||
private String getUserDetail(String accessToken, String userId) {
|
||||
String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
|
||||
private JSONObject getUserDetail(String accessToken, String userId, String userTicket) {
|
||||
// 用户基础信息
|
||||
String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
|
||||
.queryParam("access_token", accessToken)
|
||||
.queryParam("userid", userId)
|
||||
.build();
|
||||
return new HttpUtils(config.getHttpConfig()).get(userDetailUrl);
|
||||
String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
|
||||
JSONObject userInfo = checkResponse(userInfoResponse);
|
||||
|
||||
// 用户敏感信息
|
||||
if (StringUtils.isNotEmpty(userTicket)) {
|
||||
String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail")
|
||||
.queryParam("access_token", accessToken)
|
||||
.build();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("user_ticket", userTicket);
|
||||
String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, param.toJSONString()).getBody();
|
||||
JSONObject userDetail = checkResponse(userDetailResponse);
|
||||
|
||||
userInfo.putAll(userDetail);
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 爱发电
|
||||
*
|
||||
* @author handy
|
||||
*/
|
||||
public class AuthAfDianRequest extends AuthDefaultRequest {
|
||||
|
||||
public AuthAfDianRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.AFDIAN);
|
||||
}
|
||||
|
||||
public AuthAfDianRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.AFDIAN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("grant_type", "authorization_code");
|
||||
params.put("client_id", config.getClientId());
|
||||
params.put("client_secret", config.getClientSecret());
|
||||
params.put("code", authCallback.getCode());
|
||||
params.put("redirect_uri", config.getRedirectUri());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(AuthDefaultSource.AFDIAN.accessToken(), params, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
String userId = accessTokenObject.getJSONObject("data").getString("user_id");
|
||||
return AuthToken.builder().userId(userId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
return AuthUser.builder()
|
||||
.uuid(authToken.getUserId())
|
||||
.gender(AuthUserGender.UNKNOWN)
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("scope", "basic")
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("state", getRealState(state))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,9 +18,13 @@ 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.AuthChecker;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtils;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* 支付宝登录
|
||||
*
|
||||
@@ -29,24 +33,117 @@ import me.zhyd.oauth.utils.UrlBuilder;
|
||||
*/
|
||||
public class AuthAlipayRequest extends AuthDefaultRequest {
|
||||
|
||||
private AlipayClient alipayClient;
|
||||
/**
|
||||
* 支付宝公钥:当选择支付宝登录时,该值可用
|
||||
* 对应“RSA2(SHA256)密钥”中的“支付宝公钥”
|
||||
*/
|
||||
private final String alipayPublicKey;
|
||||
|
||||
private final AlipayClient alipayClient;
|
||||
|
||||
private static final String GATEWAY = "https://openapi.alipay.com/gateway.do";
|
||||
|
||||
/**
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig, java.lang.String)
|
||||
* @deprecated 请使用带有"alipayPublicKey"参数的构造方法
|
||||
*/
|
||||
@Deprecated
|
||||
public AuthAlipayRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.ALIPAY);
|
||||
this.alipayClient = new DefaultAlipayClient(AuthDefaultSource.ALIPAY.accessToken(), config.getClientId(), config.getClientSecret(), "json", "UTF-8", config
|
||||
.getAlipayPublicKey(), "RSA2");
|
||||
this(config, (String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig, java.lang.String, me.zhyd.oauth.cache.AuthStateCache)
|
||||
* @deprecated 请使用带有"alipayPublicKey"参数的构造方法
|
||||
*/
|
||||
@Deprecated
|
||||
public AuthAlipayRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.ALIPAY, authStateCache);
|
||||
this.alipayClient = new DefaultAlipayClient(AuthDefaultSource.ALIPAY.accessToken(), config.getClientId(), config.getClientSecret(), "json", "UTF-8", config
|
||||
.getAlipayPublicKey(), "RSA2");
|
||||
this(config, null, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig, java.lang.String, me.zhyd.oauth.cache.AuthStateCache, java.lang.String, java.lang.Integer)
|
||||
* @deprecated 请使用带有"alipayPublicKey"参数的构造方法
|
||||
*/
|
||||
@Deprecated
|
||||
public AuthAlipayRequest(AuthConfig config, AuthStateCache authStateCache, String proxyHost, Integer proxyPort) {
|
||||
this(config, null, authStateCache, proxyHost, proxyPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法,需要设置"alipayPublicKey"
|
||||
*
|
||||
* @param config 公共的OAuth配置
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig)
|
||||
*/
|
||||
public AuthAlipayRequest(AuthConfig config, String alipayPublicKey) {
|
||||
super(config, AuthDefaultSource.ALIPAY);
|
||||
this.alipayPublicKey = determineAlipayPublicKey(alipayPublicKey, config);
|
||||
check(config);
|
||||
this.alipayClient = new DefaultAlipayClient(GATEWAY, config.getClientId(), config.getClientSecret(), "json", "UTF-8", this.alipayPublicKey, "RSA2");
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法,需要设置"alipayPublicKey"
|
||||
*
|
||||
* @param config 公共的OAuth配置
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig, me.zhyd.oauth.cache.AuthStateCache)
|
||||
*/
|
||||
public AuthAlipayRequest(AuthConfig config, String alipayPublicKey, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.ALIPAY, authStateCache);
|
||||
this.alipayClient = new DefaultAlipayClient(AuthDefaultSource.ALIPAY.accessToken(), config.getClientId(), config.getClientSecret(),
|
||||
"json", "UTF-8", config.getAlipayPublicKey(), "RSA2", proxyHost, proxyPort);
|
||||
this.alipayPublicKey = determineAlipayPublicKey(alipayPublicKey, config);
|
||||
check(config);
|
||||
if (config.getHttpConfig() != null && config.getHttpConfig().getProxy() != null
|
||||
&& config.getHttpConfig().getProxy().address() instanceof InetSocketAddress) {
|
||||
InetSocketAddress address = (InetSocketAddress) config.getHttpConfig().getProxy().address();
|
||||
this.alipayClient = new DefaultAlipayClient(GATEWAY, config.getClientId(), config.getClientSecret(),
|
||||
"json", "UTF-8", this.alipayPublicKey, "RSA2", address.getHostName(), address.getPort());
|
||||
} else {
|
||||
this.alipayClient = new DefaultAlipayClient(GATEWAY, config.getClientId(), config.getClientSecret(),
|
||||
"json", "UTF-8", this.alipayPublicKey, "RSA2");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法,需要设置"alipayPublicKey"
|
||||
*
|
||||
* @param config 公共的OAuth配置
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @see AuthAlipayRequest#AuthAlipayRequest(me.zhyd.oauth.config.AuthConfig, me.zhyd.oauth.cache.AuthStateCache, java.lang.String, java.lang.Integer)
|
||||
*/
|
||||
public AuthAlipayRequest(AuthConfig config, String alipayPublicKey, AuthStateCache authStateCache, String proxyHost, Integer proxyPort) {
|
||||
super(config, AuthDefaultSource.ALIPAY, authStateCache);
|
||||
this.alipayPublicKey = determineAlipayPublicKey(alipayPublicKey, config);
|
||||
check(config);
|
||||
this.alipayClient = new DefaultAlipayClient(GATEWAY, config.getClientId(), config.getClientSecret(),
|
||||
"json", "UTF-8", this.alipayPublicKey, "RSA2", proxyHost, proxyPort);
|
||||
}
|
||||
|
||||
private String determineAlipayPublicKey(String alipayPublicKey, AuthConfig config) {
|
||||
return alipayPublicKey != null ? alipayPublicKey : config.getAlipayPublicKey();
|
||||
}
|
||||
|
||||
protected void check(AuthConfig config) {
|
||||
AuthChecker.checkConfig(config, AuthDefaultSource.ALIPAY);
|
||||
|
||||
if (!StringUtils.isNotEmpty(alipayPublicKey)) {
|
||||
throw new AuthException(AuthResponseStatus.PARAMETER_INCOMPLETE, AuthDefaultSource.ALIPAY);
|
||||
}
|
||||
|
||||
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1
|
||||
if (GlobalAuthUtils.isLocalHost(config.getRedirectUri())) {
|
||||
// The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, AuthDefaultSource.ALIPAY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkCode(AuthCallback authCallback) {
|
||||
if (StringUtils.isEmpty(authCallback.getAuth_code())) {
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +151,7 @@ public class AuthAlipayRequest extends AuthDefaultRequest {
|
||||
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
|
||||
request.setGrantType("authorization_code");
|
||||
request.setCode(authCallback.getAuth_code());
|
||||
AlipaySystemOauthTokenResponse response = null;
|
||||
AlipaySystemOauthTokenResponse response;
|
||||
try {
|
||||
response = this.alipayClient.execute(request);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -111,7 +111,7 @@ public class AuthAmazonRequest extends AuthDefaultRequest {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Host", "api.amazon.com");
|
||||
httpHeader.add(Constants.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=UTF-8");
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url, param, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url, param, httpHeader, false).getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(jsonObject);
|
||||
return AuthToken.builder()
|
||||
@@ -147,7 +147,7 @@ public class AuthAmazonRequest extends AuthDefaultRequest {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Host", "api.amazon.com");
|
||||
httpHeader.add("Authorization", "bearer " + accessToken);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(this.source.userInfo(), new HashMap<>(0), httpHeader, false);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(this.source.userInfo(), new HashMap<>(0), httpHeader, false).getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(jsonObject);
|
||||
|
||||
@@ -164,7 +164,7 @@ public class AuthAmazonRequest extends AuthDefaultRequest {
|
||||
}
|
||||
|
||||
private void checkToken(String accessToken) {
|
||||
String tokenInfo = new HttpUtils(config.getHttpConfig()).get("https://api.amazon.com/auth/o2/tokeninfo?access_token=" + UrlUtil.urlEncode(accessToken));
|
||||
String tokenInfo = new HttpUtils(config.getHttpConfig()).get("https://api.amazon.com/auth/o2/tokeninfo?access_token=" + UrlUtil.urlEncode(accessToken)).getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(tokenInfo);
|
||||
if (!config.getClientId().equals(jsonObject.getString("aud"))) {
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_TOKEN);
|
||||
|
||||
@@ -88,7 +88,7 @@ public class AuthBaiduRequest extends AuthDefaultRequest {
|
||||
.queryParam("client_id", this.config.getClientId())
|
||||
.queryParam("client_secret", this.config.getClientSecret())
|
||||
.build();
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(refreshUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(refreshUrl).getBody();
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(this.getAuthToken(response))
|
||||
|
||||
@@ -72,7 +72,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
@Override
|
||||
public AuthResponse login(AuthCallback authCallback) {
|
||||
try {
|
||||
AuthChecker.checkCode(source, authCallback);
|
||||
checkCode(authCallback);
|
||||
if (!config.isIgnoreCheckState()) {
|
||||
AuthChecker.checkState(authCallback.getState(), source, authStateCache);
|
||||
}
|
||||
@@ -86,13 +86,17 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkCode(AuthCallback authCallback) {
|
||||
AuthChecker.checkCode(source, authCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理{@link AuthDefaultRequest#login(AuthCallback)} 发生异常的情况,统一响应参数
|
||||
*
|
||||
* @param e 具体的异常
|
||||
* @return AuthResponse
|
||||
*/
|
||||
private AuthResponse responseError(Exception e) {
|
||||
AuthResponse responseError(Exception e) {
|
||||
int errorCode = AuthResponseStatus.FAILURE.getCode();
|
||||
String errorMsg = e.getMessage();
|
||||
if (e instanceof AuthException) {
|
||||
@@ -211,7 +215,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
* @return Response
|
||||
*/
|
||||
protected String doPostAuthorizationCode(String code) {
|
||||
return new HttpUtils(config.getHttpConfig()).post(accessTokenUrl(code));
|
||||
return new HttpUtils(config.getHttpConfig()).post(accessTokenUrl(code)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +225,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
* @return Response
|
||||
*/
|
||||
protected String doGetAuthorizationCode(String code) {
|
||||
return new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(code));
|
||||
return new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(code)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +236,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
*/
|
||||
@Deprecated
|
||||
protected String doPostUserInfo(AuthToken authToken) {
|
||||
return new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken));
|
||||
return new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,7 +246,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
* @return Response
|
||||
*/
|
||||
protected String doGetUserInfo(AuthToken authToken) {
|
||||
return new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken));
|
||||
return new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,7 +257,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
*/
|
||||
@Deprecated
|
||||
protected String doPostRevoke(AuthToken authToken) {
|
||||
return new HttpUtils(config.getHttpConfig()).post(revokeUrl(authToken));
|
||||
return new HttpUtils(config.getHttpConfig()).post(revokeUrl(authToken)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +267,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
|
||||
* @return Response
|
||||
*/
|
||||
protected String doGetRevoke(AuthToken authToken) {
|
||||
return new HttpUtils(config.getHttpConfig()).get(revokeUrl(authToken));
|
||||
return new HttpUtils(config.getHttpConfig()).get(revokeUrl(authToken)).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,7 +87,7 @@ public class AuthDouyinRequest extends AuthDefaultRequest {
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
this.checkResponse(object);
|
||||
JSONObject dataObj = object.getJSONObject("data");
|
||||
|
||||
@@ -52,7 +52,7 @@ public class AuthElemeRequest extends AuthDefaultRequest {
|
||||
form.put("grant_type", "authorization_code");
|
||||
|
||||
HttpHeader httpHeader = this.buildHeader(CONTENT_TYPE_FORM, this.getRequestId(), true);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, httpHeader, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -91,7 +91,7 @@ public class AuthElemeRequest extends AuthDefaultRequest {
|
||||
paramsMap.put("signature", signature);
|
||||
|
||||
HttpHeader httpHeader = this.buildHeader(CONTENT_TYPE_JSON, requestId, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), JSONObject.toJSONString(paramsMap), httpHeader);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), JSONObject.toJSONString(paramsMap), httpHeader).getBody();
|
||||
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
@@ -123,7 +123,7 @@ public class AuthElemeRequest extends AuthDefaultRequest {
|
||||
form.put("grant_type", "refresh_token");
|
||||
|
||||
HttpHeader httpHeader = this.buildHeader(CONTENT_TYPE_FORM, this.getRequestId(), true);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, httpHeader, false).getBody();
|
||||
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class AuthFeishuRequest extends AuthDefaultRequest {
|
||||
requestObject.put("app_id", config.getClientId());
|
||||
requestObject.put("app_secret", config.getClientSecret());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url, requestObject.toJSONString(), new HttpHeader()
|
||||
.add("Content-Type", "application/json"));
|
||||
.add("Content-Type", "application/json")).getBody();
|
||||
JSONObject jsonObject = JSON.parseObject(response);
|
||||
this.checkResponse(jsonObject);
|
||||
String appAccessToken = jsonObject.getString("app_access_token");
|
||||
@@ -80,7 +80,7 @@ public class AuthFeishuRequest extends AuthDefaultRequest {
|
||||
String accessToken = authToken.getAccessToken();
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader()
|
||||
.add("Content-Type", "application/json")
|
||||
.add("Authorization", "Bearer " + accessToken), false);
|
||||
.add("Authorization", "Bearer " + accessToken), false).getBody();
|
||||
JSONObject object = JSON.parseObject(response);
|
||||
this.checkResponse(object);
|
||||
JSONObject data = object.getJSONObject("data");
|
||||
@@ -112,7 +112,7 @@ public class AuthFeishuRequest extends AuthDefaultRequest {
|
||||
|
||||
private AuthToken getToken(JSONObject param, String url) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url, param.toJSONString(), new HttpHeader()
|
||||
.add("Content-Type", "application/json"));
|
||||
.add("Content-Type", "application/json")).getBody();
|
||||
JSONObject jsonObject = JSON.parseObject(response);
|
||||
this.checkResponse(jsonObject);
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
|
||||
@@ -52,7 +52,7 @@ public class AuthGithubRequest extends AuthDefaultRequest {
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpHeader header = new HttpHeader();
|
||||
header.add("Authorization", "token " + authToken.getAccessToken());
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(UrlBuilder.fromBaseUrl(source.userInfo()).build(), null, header, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(UrlBuilder.fromBaseUrl(source.userInfo()).build(), null, header, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object.containsKey("error"), object.getString("error_description"));
|
||||
|
||||
@@ -50,7 +50,7 @@ public class AuthGoogleRequest extends AuthDefaultRequest {
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", "Bearer " + authToken.getAccessToken());
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), null, httpHeader);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), null, httpHeader).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
return AuthUser.builder()
|
||||
|
||||
@@ -54,7 +54,7 @@ public class AuthHuaweiRequest extends AuthDefaultRequest {
|
||||
form.put("client_secret", config.getClientSecret());
|
||||
form.put("redirect_uri", config.getRedirectUri());
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false).getBody();
|
||||
return getAuthToken(response);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AuthHuaweiRequest extends AuthDefaultRequest {
|
||||
form.put("nsp_fmt", "JS");
|
||||
form.put("nsp_svc", "OpenUP.User.getInfo");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), form, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -106,7 +106,7 @@ public class AuthHuaweiRequest extends AuthDefaultRequest {
|
||||
form.put("refresh_token", authToken.getRefreshToken());
|
||||
form.put("grant_type", "refresh_token");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false).getBody();
|
||||
return AuthResponse.builder().code(SUCCESS.getCode()).data(getAuthToken(response)).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class AuthJdRequest extends AuthDefaultRequest {
|
||||
params.put("app_secret", config.getClientSecret());
|
||||
params.put("grant_type", "authorization_code");
|
||||
params.put("code", authCallback.getCode());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), params, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), params, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -70,7 +70,7 @@ public class AuthJdRequest extends AuthDefaultRequest {
|
||||
.queryParam("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
|
||||
.queryParam("v", "2.0");
|
||||
urlBuilder.queryParam("sign", GlobalAuthUtils.generateJdSignature(config.getClientSecret(), urlBuilder.getReadOnlyParams()));
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(urlBuilder.build(true));
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(urlBuilder.build(true)).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -109,7 +109,7 @@ public class AuthJdRequest extends AuthDefaultRequest {
|
||||
params.put("app_secret", config.getClientSecret());
|
||||
params.put("grant_type", "refresh_token");
|
||||
params.put("refresh_token", oldToken.getRefreshToken());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), params, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), params, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
|
||||
@@ -76,7 +76,7 @@ public class AuthKujialeRequest extends AuthDefaultRequest {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("open_id", openId)
|
||||
.build());
|
||||
.build()).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
if (!"0".equals(object.getString("c"))) {
|
||||
throw new AuthException(object.getString("m"));
|
||||
@@ -103,14 +103,14 @@ public class AuthKujialeRequest extends AuthDefaultRequest {
|
||||
private String getOpenId(AuthToken authToken) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(UrlBuilder.fromBaseUrl("https://oauth.kujiale.com/oauth2/auth/user")
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.build());
|
||||
.build()).getBody();
|
||||
JSONObject accessTokenObject = checkResponse(response);
|
||||
return accessTokenObject.getString("d");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(refreshTokenUrl(authToken.getRefreshToken()));
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(refreshTokenUrl(authToken.getRefreshToken())).getBody();
|
||||
return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(getAuthToken(response)).build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,14 +37,29 @@ public class AuthLineRequest extends AuthDefaultRequest {
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return this.getToken(accessTokenUrl(authCallback.getCode()));
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("grant_type", "authorization_code");
|
||||
params.put("code", authCallback.getCode());
|
||||
params.put("redirect_uri", config.getRedirectUri());
|
||||
params.put("client_id", config.getClientId());
|
||||
params.put("client_secret", config.getClientSecret());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), params, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
return AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.idToken(accessTokenObject.getString("id_token"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader()
|
||||
.add("Content-Type", "application/x-www-form-urlencoded")
|
||||
.add("Authorization", "Bearer ".concat(authToken.getAccessToken())), false);
|
||||
.add("Authorization", "Bearer ".concat(authToken.getAccessToken())), false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(object)
|
||||
@@ -65,7 +80,7 @@ public class AuthLineRequest extends AuthDefaultRequest {
|
||||
params.put("access_token", authToken.getAccessToken());
|
||||
params.put("client_id", config.getClientId());
|
||||
params.put("client_secret", config.getClientSecret());
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).post(source.revoke(), params, false);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).post(source.revoke(), params, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
// 返回1表示取消授权成功,否则失败
|
||||
AuthResponseStatus status = object.getBooleanValue("revoked") ? AuthResponseStatus.SUCCESS : AuthResponseStatus.FAILURE;
|
||||
@@ -74,28 +89,23 @@ public class AuthLineRequest extends AuthDefaultRequest {
|
||||
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken oldToken) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("grant_type", "refresh_token");
|
||||
params.put("refresh_token", oldToken.getRefreshToken());
|
||||
params.put("client_id", config.getClientId());
|
||||
params.put("client_secret", config.getClientSecret());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), params, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(this.getToken(refreshTokenUrl(oldToken.getRefreshToken())))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token,适用于获取access_token和刷新token
|
||||
*
|
||||
* @param accessTokenUrl 实际请求token的地址
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl);
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
return AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.idToken(accessTokenObject.getString("id_token"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.data(AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.idToken(accessTokenObject.getString("id_token"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
|
||||
httpHeader.add("Connection", "Keep-Alive");
|
||||
httpHeader.add("Authorization", "Bearer " + accessToken);
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false).getBody();
|
||||
JSONObject userInfoObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(userInfoObject);
|
||||
@@ -138,7 +138,9 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
|
||||
httpHeader.add("Connection", "Keep-Alive");
|
||||
httpHeader.add("Authorization", "Bearer " + accessToken);
|
||||
|
||||
String emailResponse = new HttpUtils(config.getHttpConfig()).get("https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))", null, httpHeader, false);
|
||||
String emailResponse = new HttpUtils(config.getHttpConfig())
|
||||
.get("https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))", null, httpHeader, false)
|
||||
.getBody();
|
||||
JSONObject emailObj = JSONObject.parseObject(emailResponse);
|
||||
|
||||
this.checkResponse(emailObj);
|
||||
@@ -178,7 +180,7 @@ public class AuthLinkedinRequest extends AuthDefaultRequest {
|
||||
httpHeader.add("Host", "www.linkedin.com");
|
||||
httpHeader.add(Constants.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, null, httpHeader);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, null, httpHeader).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class AuthMeituanRequest extends AuthDefaultRequest {
|
||||
form.put("code", authCallback.getCode());
|
||||
form.put("grant_type", "authorization_code");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -60,7 +60,7 @@ public class AuthMeituanRequest extends AuthDefaultRequest {
|
||||
form.put("secret", config.getClientSecret());
|
||||
form.put("access_token", authToken.getAccessToken());
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), form, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -85,7 +85,7 @@ public class AuthMeituanRequest extends AuthDefaultRequest {
|
||||
form.put("refresh_token", oldToken.getRefreshToken());
|
||||
form.put("grant_type", "refresh_token");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
|
||||
@@ -43,7 +43,7 @@ public class AuthMiRequest extends AuthDefaultRequest {
|
||||
}
|
||||
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody();
|
||||
String jsonStr = response.replace(PREFIX, Constants.EMPTY);
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(jsonStr);
|
||||
|
||||
@@ -91,7 +91,7 @@ public class AuthMiRequest extends AuthDefaultRequest {
|
||||
String emailPhoneUrl = MessageFormat.format("{0}?clientId={1}&token={2}", "https://open.account.xiaomi.com/user/phoneAndEmail", config
|
||||
.getClientId(), authToken.getAccessToken());
|
||||
|
||||
String emailResponse = new HttpUtils(config.getHttpConfig()).get(emailPhoneUrl);
|
||||
String emailResponse = new HttpUtils(config.getHttpConfig()).get(emailPhoneUrl).getBody();
|
||||
JSONObject userEmailPhone = JSONObject.parseObject(emailResponse);
|
||||
if (!"error".equalsIgnoreCase(userEmailPhone.getString("result"))) {
|
||||
JSONObject emailPhone = userEmailPhone.getJSONObject("data");
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
|
||||
/**
|
||||
* 微软中国登录(世纪华联)
|
||||
*
|
||||
* @author mroldx (xzfqq5201314@gmail.com)
|
||||
* @since 1.16.4
|
||||
*/
|
||||
public class AuthMicrosoftCnRequest extends AbstractAuthMicrosoftRequest {
|
||||
|
||||
public AuthMicrosoftCnRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.MICROSOFT_CN);
|
||||
}
|
||||
|
||||
public AuthMicrosoftCnRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.MICROSOFT_CN, authStateCache);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +1,18 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.xkcoding.http.support.HttpHeader;
|
||||
import com.xkcoding.http.util.MapUtil;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.enums.scope.AuthMicrosoftScope;
|
||||
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.AuthScopeUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微软登录
|
||||
* update 2021-08-24 mroldx (xzfqq5201314@gmail.com)
|
||||
*
|
||||
* @author yangkai.shen (https://xkcoding.com)
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class AuthMicrosoftRequest extends AuthDefaultRequest {
|
||||
public class AuthMicrosoftRequest extends AbstractAuthMicrosoftRequest {
|
||||
|
||||
public AuthMicrosoftRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.MICROSOFT);
|
||||
}
|
||||
@@ -35,145 +21,4 @@ public class AuthMicrosoftRequest extends AuthDefaultRequest {
|
||||
super(config, AuthDefaultSource.MICROSOFT, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
return getToken(accessTokenUrl(authCallback.getCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token,适用于获取access_token和刷新token
|
||||
*
|
||||
* @param accessTokenUrl 实际请求token的地址
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
|
||||
Map<String, String> form = MapUtil.parseStringToMap(accessTokenUrl, false);
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, form, httpHeader, false);
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查响应内容是否正确
|
||||
*
|
||||
* @param object 请求响应内容
|
||||
*/
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String token = authToken.getAccessToken();
|
||||
String tokenType = authToken.getTokenType();
|
||||
String jwt = tokenType + " " + token;
|
||||
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", jwt);
|
||||
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false);
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(object)
|
||||
.uuid(object.getString("id"))
|
||||
.username(object.getString("userPrincipalName"))
|
||||
.nickname(object.getString("displayName"))
|
||||
.location(object.getString("officeLocation"))
|
||||
.email(object.getString("mail"))
|
||||
.gender(AuthUserGender.UNKNOWN)
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新access token (续期)
|
||||
*
|
||||
* @param authToken 登录成功后返回的Token信息
|
||||
* @return AuthResponse
|
||||
*/
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(getToken(refreshTokenUrl(authToken.getRefreshToken())))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
* @since 1.9.3
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(super.authorize(state))
|
||||
.queryParam("response_mode", "query")
|
||||
.queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权code
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.queryParam("code", code)
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("client_secret", config.getClientSecret())
|
||||
.queryParam("grant_type", "authorization_code")
|
||||
.queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.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()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param refreshToken 用户授权后的token
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String refreshTokenUrl(String refreshToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.refresh())
|
||||
.queryParam("client_id", config.getClientId())
|
||||
.queryParam("client_secret", config.getClientSecret())
|
||||
.queryParam("refresh_token", refreshToken)
|
||||
.queryParam("grant_type", "refresh_token")
|
||||
.queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthMicrosoftScope.values())))
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class AuthOktaRequest extends AuthDefaultRequest {
|
||||
.add("accept", "application/json")
|
||||
.add("content-type", "application/x-www-form-urlencoded")
|
||||
.add("Authorization", "Basic " + Base64Utils.encode(config.getClientId().concat(":").concat(config.getClientSecret())));
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(tokenUrl, null, header, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(tokenUrl, null, header, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
return AuthToken.builder()
|
||||
@@ -82,7 +82,7 @@ public class AuthOktaRequest extends AuthDefaultRequest {
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpHeader header = new HttpHeader()
|
||||
.add("Authorization", "Bearer " + authToken.getAccessToken());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), null, header, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(userInfoUrl(authToken), null, header, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
this.checkResponse(object);
|
||||
JSONObject address = object.getJSONObject("address");
|
||||
|
||||
@@ -50,7 +50,7 @@ public class AuthPinterestRequest extends AuthDefaultRequest {
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String userinfoUrl = userInfoUrl(authToken);
|
||||
// TODO: 是否需要 .setFollowRedirects(true)
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userinfoUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userinfoUrl).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
this.checkResponse(object);
|
||||
JSONObject userObj = object.getJSONObject("data");
|
||||
|
||||
@@ -41,7 +41,7 @@ public class AuthProginnRequest extends AuthDefaultRequest {
|
||||
params.put("client_secret", config.getClientSecret());
|
||||
params.put("grant_type", "authorization_code");
|
||||
params.put("redirect_uri", config.getRedirectUri());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(AuthDefaultSource.PROGINN.accessToken(), params, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(AuthDefaultSource.PROGINN.accessToken(), params, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
return AuthToken.builder()
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AuthQqRequest extends AuthDefaultRequest {
|
||||
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken authToken) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(refreshTokenUrl(authToken.getRefreshToken()));
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(refreshTokenUrl(authToken.getRefreshToken())).getBody();
|
||||
return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(getAuthToken(response)).build();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class AuthQqRequest extends AuthDefaultRequest {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(UrlBuilder.fromBaseUrl("https://graph.qq.com/oauth2.0/me")
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("unionid", config.isUnionId() ? 1 : 0)
|
||||
.build());
|
||||
.build()).getBody();
|
||||
String removePrefix = response.replace("callback(", "");
|
||||
String removeSuffix = removePrefix.replace(");", "");
|
||||
String openId = removeSuffix.trim();
|
||||
|
||||
@@ -68,7 +68,7 @@ public class AuthRenrenRequest extends AuthDefaultRequest {
|
||||
}
|
||||
|
||||
private AuthToken getToken(String url) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(url).getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
if (jsonObject.containsKey("error")) {
|
||||
throw new AuthException("Failed to get token from Renren: " + jsonObject);
|
||||
|
||||
@@ -38,7 +38,8 @@ public class AuthSlackRequest extends AuthDefaultRequest {
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpHeader header = new HttpHeader()
|
||||
.add("Content-Type", "application/x-www-form-urlencoded");
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode()), null, header, false);
|
||||
String response = new HttpUtils(config.getHttpConfig())
|
||||
.get(accessTokenUrl(authCallback.getCode()), null, header, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
return AuthToken.builder()
|
||||
@@ -54,7 +55,8 @@ public class AuthSlackRequest extends AuthDefaultRequest {
|
||||
HttpHeader header = new HttpHeader()
|
||||
.add("Content-Type", "application/x-www-form-urlencoded")
|
||||
.add("Authorization", "Bearer ".concat(authToken.getAccessToken()));
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, header, false);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig())
|
||||
.get(userInfoUrl(authToken), null, header, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
JSONObject user = object.getJSONObject("user");
|
||||
@@ -77,7 +79,8 @@ public class AuthSlackRequest extends AuthDefaultRequest {
|
||||
HttpHeader header = new HttpHeader()
|
||||
.add("Content-Type", "application/x-www-form-urlencoded")
|
||||
.add("Authorization", "Bearer ".concat(authToken.getAccessToken()));
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(source.revoke(), null, header, false);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig())
|
||||
.get(source.revoke(), null, header, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
// 返回1表示取消授权成功,否则失败
|
||||
|
||||
@@ -42,7 +42,7 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest {
|
||||
Map<String, String> form = MapUtil.parseStringToMap(accessTokenUrl, false);
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add(Constants.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, form, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl, form, httpHeader, false).getBody();
|
||||
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
@@ -60,7 +60,7 @@ public class AuthStackOverflowRequest extends AuthDefaultRequest {
|
||||
.queryParam("site", "stackoverflow")
|
||||
.queryParam("key", this.config.getStackOverflowKey())
|
||||
.build();
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userInfoUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
this.checkResponse(object);
|
||||
JSONObject userObj = object.getJSONArray("items").getJSONObject(0);
|
||||
|
||||
@@ -81,7 +81,7 @@ public class AuthTaobaoRequest extends AuthDefaultRequest {
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken oldToken) {
|
||||
String tokenUrl = refreshTokenUrl(oldToken.getRefreshToken());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(tokenUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(tokenUrl).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
|
||||
@@ -45,7 +45,7 @@ public class AuthTeambitionRequest extends AuthDefaultRequest {
|
||||
form.put("code", authCallback.getCode());
|
||||
form.put("grant_type", "code");
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
@@ -63,7 +63,8 @@ public class AuthTeambitionRequest extends AuthDefaultRequest {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", "OAuth2 " + accessToken);
|
||||
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig())
|
||||
.get(source.userInfo(), null, httpHeader, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
@@ -93,7 +94,7 @@ public class AuthTeambitionRequest extends AuthDefaultRequest {
|
||||
Map<String, String> form = new HashMap<>(4);
|
||||
form.put("_userId", uid);
|
||||
form.put("refresh_token", refreshToken);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false).getBody();
|
||||
JSONObject refreshTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(refreshTokenObject);
|
||||
|
||||
@@ -69,10 +69,8 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", header);
|
||||
httpHeader.add("User-Agent", "themattharris' HTTP Client");
|
||||
httpHeader.add("Host", "api.twitter.com");
|
||||
httpHeader.add("Accept", "*/*");
|
||||
String requestToken = new HttpUtils(config.getHttpConfig()).post(baseUrl, null, httpHeader);
|
||||
httpHeader.add("User-Agent", "'JustAuth' HTTP Client Simple-Http");
|
||||
String requestToken = new HttpUtils(config.getHttpConfig()).post(baseUrl, null, httpHeader).getBody();
|
||||
|
||||
Map<String, String> res = MapUtil.parseStringToMap(requestToken, false);
|
||||
|
||||
@@ -104,7 +102,7 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
|
||||
Map<String, String> form = new HashMap<>(3);
|
||||
form.put("oauth_verifier", authCallback.getOauth_verifier());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, httpHeader, false).getBody();
|
||||
|
||||
Map<String, String> requestToken = MapUtil.parseStringToMap(response, false);
|
||||
|
||||
@@ -132,7 +130,8 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", header);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false);
|
||||
String response = new HttpUtils(config.getHttpConfig())
|
||||
.get(userInfoUrl(authToken), null, httpHeader, false).getBody();
|
||||
JSONObject userInfo = JSONObject.parseObject(response);
|
||||
|
||||
return AuthUser.builder()
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
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;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 企业微信第三方二维码登录
|
||||
* </p>
|
||||
*
|
||||
* @author zhengjx
|
||||
* @since 1.16.3
|
||||
*/
|
||||
public class AuthWeChatEnterpriseThirdQrcodeRequest extends AbstractAuthWeChatEnterpriseRequest {
|
||||
public AuthWeChatEnterpriseThirdQrcodeRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.WECHAT_ENTERPRISE_QRCODE_THIRD);
|
||||
}
|
||||
|
||||
public AuthWeChatEnterpriseThirdQrcodeRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.WECHAT_ENTERPRISE_QRCODE_THIRD, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("appid", config.getClientId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("state", getRealState(state))
|
||||
.queryParam("usertype", config.getUsertype())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse login(AuthCallback authCallback) {
|
||||
try {
|
||||
if (!config.isIgnoreCheckState()) {
|
||||
AuthChecker.checkState(authCallback.getState(), source, authStateCache);
|
||||
}
|
||||
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);
|
||||
return this.responseError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
try {
|
||||
String response = doGetAuthorizationCode(accessTokenUrl());
|
||||
JSONObject object = this.checkResponse(response);
|
||||
AuthToken authToken = AuthToken.builder()
|
||||
.accessToken(object.getString("provider_access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.build();
|
||||
return authToken;
|
||||
} catch (Exception e) {
|
||||
throw new AuthException("企业微信获取token失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetAuthorizationCode(String code) {
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("corpid", config.getClientId());
|
||||
data.put("provider_secret", config.getClientSecret());
|
||||
return new HttpUtils(config.getHttpConfig()).post(accessTokenUrl(code), data.toJSONString()).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token的URL
|
||||
*
|
||||
* @return accessTokenUrl
|
||||
*/
|
||||
protected String accessTokenUrl() {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
JSONObject response = this.checkResponse(doGetUserInfo(authToken));
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetUserInfo(AuthToken authToken) {
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("auth_code", authToken.getCode());
|
||||
return new HttpUtils(config.getHttpConfig())
|
||||
.post(userInfoUrl(authToken), data.toJSONString()).getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("access_token", authToken.getAccessToken()).
|
||||
build();
|
||||
}
|
||||
|
||||
private JSONObject checkResponse(String response) {
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
|
||||
throw new AuthException(object.getString("errmsg"), source);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.enums.scope.AuthWeChatEnterpriseWebScope;
|
||||
import me.zhyd.oauth.utils.AuthScopeUtils;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,8 @@ public class AuthWeChatEnterpriseWebRequest extends AbstractAuthWeChatEnterprise
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("appid", config.getClientId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("agentid", config.getAgentId())
|
||||
.queryParam("redirect_uri", GlobalAuthUtils.urlEncode(config.getRedirectUri()))
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("scope", this.getScopes(",", false, AuthScopeUtils.getDefaultScopes(AuthWeChatEnterpriseWebScope.values())))
|
||||
.queryParam("state", getRealState(state).concat("#wechat_redirect"))
|
||||
|
||||
@@ -12,10 +12,7 @@ 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.AuthScopeUtils;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
import me.zhyd.oauth.utils.*;
|
||||
|
||||
/**
|
||||
* 微信公众平台登录
|
||||
@@ -47,17 +44,26 @@ public class AuthWeChatMpRequest extends AuthDefaultRequest {
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String openId = authToken.getOpenId();
|
||||
|
||||
String scope = authToken.getScope();
|
||||
if (!StringUtils.isEmpty(scope) && !scope.contains("snsapi_userinfo")) {
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(JSONObject.parseObject(JSONObject.toJSONString(authToken)))
|
||||
.uuid(openId)
|
||||
.snapshotUser(authToken.isSnapshotUser())
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
String response = doGetUserInfo(authToken);
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(object);
|
||||
|
||||
String location = String.format("%s-%s-%s", object.getString("country"), object.getString("province"), object.getString("city"));
|
||||
|
||||
if (object.containsKey("unionid")) {
|
||||
authToken.setUnionId(object.getString("unionid"));
|
||||
}
|
||||
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(object)
|
||||
.username(object.getString("nickname"))
|
||||
@@ -65,6 +71,7 @@ public class AuthWeChatMpRequest extends AuthDefaultRequest {
|
||||
.avatar(object.getString("headimgurl"))
|
||||
.location(location)
|
||||
.uuid(openId)
|
||||
.snapshotUser(authToken.isSnapshotUser())
|
||||
.gender(AuthUserGender.getWechatRealGender(object.getString("sex")))
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
@@ -97,7 +104,7 @@ public class AuthWeChatMpRequest extends AuthDefaultRequest {
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
@@ -108,6 +115,7 @@ public class AuthWeChatMpRequest extends AuthDefaultRequest {
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.openId(accessTokenObject.getString("openid"))
|
||||
.scope(accessTokenObject.getString("scope"))
|
||||
.snapshotUser(accessTokenObject.getIntValue("is_snapshotuser") == 1)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ public class AuthWeChatOpenRequest extends AuthDefaultRequest {
|
||||
* @return token对象
|
||||
*/
|
||||
private AuthToken getToken(String accessTokenUrl) {
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl);
|
||||
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
|
||||
this.checkResponse(accessTokenObject);
|
||||
|
||||
@@ -56,7 +56,8 @@ public class AuthWeiboRequest extends AuthDefaultRequest {
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
httpHeader.add("Authorization", "OAuth2 " + oauthParam);
|
||||
httpHeader.add("API-RemoteIP", IpUtils.getLocalIp());
|
||||
String userInfo = new HttpUtils(config.getHttpConfig()).get(userInfoUrl(authToken), null, httpHeader, false);
|
||||
String userInfo = new HttpUtils(config.getHttpConfig())
|
||||
.get(userInfoUrl(authToken), null, httpHeader, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("error"));
|
||||
|
||||
@@ -50,7 +50,7 @@ public class AuthXmlyRequest extends AuthDefaultRequest {
|
||||
map.put("device_id", config.getDeviceId());
|
||||
map.put("grant_type", "authorization_code");
|
||||
map.put("redirect_uri", config.getRedirectUri());
|
||||
String response = HttpUtil.post(source.accessToken(), map, true);
|
||||
String response = HttpUtil.post(source.accessToken(), map, true).getBody();
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
|
||||
@@ -97,7 +97,7 @@ public class AuthXmlyRequest extends AuthDefaultRequest {
|
||||
map.put("pack_id", config.getPackId());
|
||||
map.put("access_token", authToken.getAccessToken());
|
||||
map.put("sig", GlobalAuthUtils.generateXmlySignature(map, config.getClientSecret()));
|
||||
String rawUserInfo = HttpUtil.get(source.userInfo(), map, false);
|
||||
String rawUserInfo = HttpUtil.get(source.userInfo(), map, false).getBody();
|
||||
JSONObject object = JSONObject.parseObject(rawUserInfo);
|
||||
checkResponse(object);
|
||||
return AuthUser.builder()
|
||||
|
||||
@@ -27,9 +27,6 @@ public class AuthChecker {
|
||||
public static boolean isSupportedAuth(AuthConfig config, AuthSource source) {
|
||||
boolean isSupported = StringUtils.isNotEmpty(config.getClientId())
|
||||
&& StringUtils.isNotEmpty(config.getClientSecret());
|
||||
if (isSupported && AuthDefaultSource.ALIPAY == source) {
|
||||
isSupported = StringUtils.isNotEmpty(config.getAlipayPublicKey());
|
||||
}
|
||||
if (isSupported && AuthDefaultSource.STACK_OVERFLOW == source) {
|
||||
isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
|
||||
}
|
||||
@@ -71,9 +68,14 @@ public class AuthChecker {
|
||||
// Facebook's redirect uri must use the HTTPS protocol
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
||||
}
|
||||
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1
|
||||
if (AuthDefaultSource.ALIPAY == source && GlobalAuthUtils.isLocalHost(redirectUri)) {
|
||||
// The redirect uri of alipay is forbidden to use localhost or 127.0.0.1
|
||||
// 微软的回调地址必须为https的链接或者localhost,不允许使用http
|
||||
if (AuthDefaultSource.MICROSOFT == source && !GlobalAuthUtils.isHttpsProtocolOrLocalHost(redirectUri)) {
|
||||
// Microsoft's redirect uri must use the HTTPS or localhost
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
||||
}
|
||||
// 微软中国的回调地址必须为https的链接或者localhost,不允许使用http
|
||||
if (AuthDefaultSource.MICROSOFT_CN == source && !GlobalAuthUtils.isHttpsProtocolOrLocalHost(redirectUri)) {
|
||||
// Microsoft's redirect uri must use the HTTPS or localhost
|
||||
throw new AuthException(AuthResponseStatus.ILLEGAL_REDIRECT_URI, source);
|
||||
}
|
||||
}
|
||||
@@ -93,9 +95,7 @@ public class AuthChecker {
|
||||
return;
|
||||
}
|
||||
String code = callback.getCode();
|
||||
if (source == AuthDefaultSource.ALIPAY) {
|
||||
code = callback.getAuth_code();
|
||||
} else if (source == AuthDefaultSource.HUAWEI) {
|
||||
if (source == AuthDefaultSource.HUAWEI) {
|
||||
code = callback.getAuthorization_code();
|
||||
}
|
||||
if (StringUtils.isEmpty(code)) {
|
||||
|
||||
@@ -175,6 +175,19 @@ public class GlobalAuthUtils {
|
||||
return StringUtils.isEmpty(url) || url.contains("127.0.0.1") || url.contains("localhost");
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为https协议或本地主机(域名)
|
||||
*
|
||||
* @param url 待验证的url
|
||||
* @return true: https协议或本地主机 false: 非https协议或本机主机
|
||||
*/
|
||||
public static boolean isHttpsProtocolOrLocalHost(String url) {
|
||||
if (StringUtils.isEmpty(url)) {
|
||||
return false;
|
||||
}
|
||||
return isHttpsProtocol(url) || isLocalHost(url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate nonce with given length
|
||||
|
||||
@@ -3,17 +3,22 @@ package me.zhyd.oauth.utils;
|
||||
import com.xkcoding.http.HttpUtil;
|
||||
import com.xkcoding.http.config.HttpConfig;
|
||||
import com.xkcoding.http.support.HttpHeader;
|
||||
import com.xkcoding.http.support.SimpleHttpResponse;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HttpUtil 工具,统一处理 http 请求,方便对 simple-http 做定制
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class HttpUtils {
|
||||
|
||||
private SimpleHttpResponse httpResponse;
|
||||
|
||||
public HttpUtils(HttpConfig config) {
|
||||
HttpUtil.setConfig(config);
|
||||
}
|
||||
@@ -26,10 +31,11 @@ public class HttpUtils {
|
||||
* GET 请求
|
||||
*
|
||||
* @param url URL
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String get(String url) {
|
||||
return HttpUtil.get(url);
|
||||
public HttpUtils get(String url) {
|
||||
this.httpResponse = HttpUtil.get(url, null, null, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,20 +45,22 @@ public class HttpUtils {
|
||||
* @param params 参数
|
||||
* @param header 请求头
|
||||
* @param encode 是否需要 url encode
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String get(String url, Map<String, String> params, HttpHeader header, boolean encode) {
|
||||
return HttpUtil.get(url, params, header, encode);
|
||||
public HttpUtils get(String url, Map<String, String> params, HttpHeader header, boolean encode) {
|
||||
this.httpResponse = HttpUtil.get(url, params, header, encode);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 请求
|
||||
*
|
||||
* @param url URL
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String post(String url) {
|
||||
return HttpUtil.post(url);
|
||||
public HttpUtils post(String url) {
|
||||
this.httpResponse = HttpUtil.post(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +68,11 @@ public class HttpUtils {
|
||||
*
|
||||
* @param url URL
|
||||
* @param data JSON 参数
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String post(String url, String data) {
|
||||
return HttpUtil.post(url, data);
|
||||
public HttpUtils post(String url, String data) {
|
||||
this.httpResponse = HttpUtil.post(url, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,10 +81,11 @@ public class HttpUtils {
|
||||
* @param url URL
|
||||
* @param data JSON 参数
|
||||
* @param header 请求头
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String post(String url, String data, HttpHeader header) {
|
||||
return HttpUtil.post(url, data, header);
|
||||
public HttpUtils post(String url, String data, HttpHeader header) {
|
||||
this.httpResponse = HttpUtil.post(url, data, header);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,10 +94,11 @@ public class HttpUtils {
|
||||
* @param url URL
|
||||
* @param params form 参数
|
||||
* @param encode 是否需要 url encode
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String post(String url, Map<String, String> params, boolean encode) {
|
||||
return HttpUtil.post(url, params, encode);
|
||||
public HttpUtils post(String url, Map<String, String> params, boolean encode) {
|
||||
this.httpResponse = HttpUtil.post(url, params, encode);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +108,28 @@ public class HttpUtils {
|
||||
* @param params form 参数
|
||||
* @param header 请求头
|
||||
* @param encode 是否需要 url encode
|
||||
* @return 结果
|
||||
* @return HttpUtils
|
||||
*/
|
||||
public String post(String url, Map<String, String> params, HttpHeader header, boolean encode) {
|
||||
return HttpUtil.post(url, params, header, encode);
|
||||
public HttpUtils post(String url, Map<String, String> params, HttpHeader header, boolean encode) {
|
||||
this.httpResponse = HttpUtil.post(url, params, header, encode);
|
||||
return this;
|
||||
}
|
||||
|
||||
private HttpUtils check() {
|
||||
if (null == httpResponse) {
|
||||
throw new AuthException("Invalid SimpleHttpResponse.");
|
||||
}
|
||||
if (!httpResponse.isSuccess()) {
|
||||
throw new AuthException(httpResponse.getError());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return this.check().getHttpResponse().getBody();
|
||||
}
|
||||
|
||||
public SimpleHttpResponse getHttpResponse() {
|
||||
return httpResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package me.zhyd.oauth;
|
||||
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthDefaultSource;
|
||||
import me.zhyd.oauth.config.AuthExtendSource;
|
||||
import me.zhyd.oauth.request.*;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AuthRequestBuilderTest {
|
||||
|
||||
/**
|
||||
* 示例:一般场景下通过 AuthRequestBuilder 构建 AuthRequest
|
||||
*/
|
||||
@Test
|
||||
public void build2() {
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("github")
|
||||
.authConfig(AuthConfig.builder()
|
||||
.clientId("a")
|
||||
.clientSecret("a")
|
||||
.redirectUri("https://www.justauth.cn")
|
||||
.build())
|
||||
.build();
|
||||
Assert.assertTrue(authRequest instanceof AuthGithubRequest);
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例:AuthConfig 需要动态获取的场景下通过 AuthRequestBuilder 构建 AuthRequest
|
||||
*/
|
||||
@Test
|
||||
public void build() {
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source("gitee")
|
||||
.authConfig((source) -> {
|
||||
// 通过 source 动态获取 AuthConfig
|
||||
// 此处可以灵活的从 sql 中取配置也可以从配置文件中取配置
|
||||
return AuthConfig.builder()
|
||||
.clientId(source)
|
||||
.clientSecret(source)
|
||||
.redirectUri("https://www.justauth.cn/" + source)
|
||||
.build();
|
||||
})
|
||||
.build();
|
||||
Assert.assertTrue(authRequest instanceof AuthGiteeRequest);
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例:自定义实现的 AuthRequest,通过 AuthRequestBuilder 构建 AuthRequest
|
||||
*/
|
||||
@Test
|
||||
public void build3() {
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
// 关键点:将自定义的 AuthSource 配置上
|
||||
.extendSource(AuthExtendSource.values())
|
||||
.source("other")
|
||||
.authConfig(AuthConfig.builder()
|
||||
.clientId("a")
|
||||
.clientSecret("a")
|
||||
.redirectUri("https://www.justauth.cn")
|
||||
.build())
|
||||
.build();
|
||||
Assert.assertTrue(authRequest instanceof AuthExtendRequest);
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试不同平台
|
||||
*/
|
||||
@Test
|
||||
public void build4() {
|
||||
AuthConfig config = AuthConfig.builder()
|
||||
.clientId("a")
|
||||
.clientSecret("a")
|
||||
.redirectUri("https://www.justauth.cn")
|
||||
.authServerId("asd")
|
||||
.agentId("asd")
|
||||
.domainPrefix("asd")
|
||||
.stackOverflowKey("asd")
|
||||
.deviceId("asd")
|
||||
.clientOsType(3)
|
||||
.build();
|
||||
|
||||
for (AuthDefaultSource value : AuthDefaultSource.values()) {
|
||||
switch (value) {
|
||||
case TWITTER:
|
||||
System.out.println(value.getTargetClass());
|
||||
System.out.println("忽略 twitter");
|
||||
continue;
|
||||
case ALIPAY: {
|
||||
// 单独给Alipay执行测试
|
||||
AuthRequest authRequest = new AuthAlipayRequest(config, "asd");
|
||||
System.out.println(value.getTargetClass());
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
AuthRequest authRequest = AuthRequestBuilder.builder()
|
||||
.source(value.getName())
|
||||
.authConfig(config)
|
||||
.build();
|
||||
System.out.println(value.getTargetClass());
|
||||
System.out.println(authRequest.authorize(AuthStateUtils.createState()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package me.zhyd.oauth.config;
|
||||
|
||||
import me.zhyd.oauth.request.AuthDefaultRequest;
|
||||
import me.zhyd.oauth.request.AuthExtendRequest;
|
||||
|
||||
/**
|
||||
* 测试自定义实现{@link AuthSource}接口后的枚举类
|
||||
*
|
||||
@@ -59,5 +62,11 @@ public enum AuthExtendSource implements AuthSource {
|
||||
public String refresh() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthDefaultRequest> getTargetClass() {
|
||||
return AuthExtendRequest.class;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public class AuthUserTest {
|
||||
.nickname("test")
|
||||
.build();
|
||||
String json = JSON.toJSONString(user);
|
||||
Assert.assertEquals(json, "{\"nickname\":\"test\"}");
|
||||
Assert.assertEquals(json, "{\"nickname\":\"test\",\"snapshotUser\":false}");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AuthWeChatEnterpriseWebRequestTest {
|
||||
|
||||
@Test
|
||||
public void authorize() {
|
||||
AuthRequest request = new AuthWeChatEnterpriseWebRequest(AuthConfig.builder()
|
||||
.clientId("a")
|
||||
.clientSecret("a")
|
||||
.redirectUri("https://www.justauth.cn")
|
||||
.build());
|
||||
System.out.println(request.authorize(AuthStateUtils.createState()));
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ public class GlobalAuthUtilsTest {
|
||||
oauthParams.forEach((k, v) -> oauthParams.put(k, "\"" + GlobalAuthUtils.urlEncode(v) + "\""));
|
||||
|
||||
String actual = "OAuth " + GlobalAuthUtils.parseMapToString(oauthParams, false).replaceAll("&", ", ");
|
||||
assertEquals("OAuth oauth_nonce=\"sTj7Ivg73u052eXstpoS1AWQCynuDEPN\", oauth_signature=\"yHHq2J1W5QLAO8gGipnY1V%2Bzxqk%3D\", oauth_token=\"1961977975-PcFQaCnpN9h9xqtqHwHlpGBXFrHJ9bOLy7OtGAL\", oauth_consumer_key=\"HD0XLqzi5Wz0G08rh45Cg8mgh\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1569751082\", oauth_version=\"1.0\"", actual);
|
||||
assertEquals("OAuth oauth_nonce=\"sTj7Ivg73u052eXstpoS1AWQCynuDEPN\", oauth_signature=\"OsqHjRmBf7syxlz8lB7MRdzqEjY%3D\", oauth_token=\"1961977975-PcFQaCnpN9h9xqtqHwHlpGBXFrHJ9bOLy7OtGAL\", oauth_consumer_key=\"HD0XLqzi5Wz0G08rh45Cg8mgh\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1569751082\", oauth_version=\"1.0\"", actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -200,7 +200,7 @@ public class GlobalAuthUtilsTest {
|
||||
queryParams.put("name", "你好");
|
||||
queryParams.put("gender", "male");
|
||||
|
||||
assertEquals("J6MAQH1kcgUdj2jmygN3rdfI4lo=", GlobalAuthUtils.generateTwitterSignature(queryParams, "GET", TWITTER.userInfo(), "xxxxx", "xxxxx"));
|
||||
assertEquals("20FYnV2aZnxNQtp+I0tpMRTvcx0=", GlobalAuthUtils.generateTwitterSignature(queryParams, "GET", TWITTER.userInfo(), "xxxxx", "xxxxx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||