mirror of
https://gitee.com/yadong.zhang/JustAuth.git
synced 2025-12-06 16:58:24 +08:00
✨ 合并pr,增加单测以及集成企业微信
This commit is contained in:
commit
48a368b516
@ -6,7 +6,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.9.6-blue.svg" ></img>
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.10.0-blue.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://gitee.com/yadong.zhang/JustAuth/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/apm/l/vim-mode.svg?color=yellow" ></img>
|
||||
@ -15,7 +15,7 @@
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.9.6-orange.svg" ></img>
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.10.0-orange.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://docs.justauth.whnb.wang" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
@ -89,7 +89,7 @@ JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.9.6</version>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://search.maven.org/search?q=JustAuth">
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.9.6-blue.svg" ></img>
|
||||
<img src="https://img.shields.io/badge/Maven Central-1.10.0-blue.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://gitee.com/yadong.zhang/JustAuth/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/apm/l/vim-mode.svg?color=yellow" ></img>
|
||||
@ -18,7 +18,7 @@
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.9.6-orange.svg" ></img>
|
||||
<img src="https://img.shields.io/badge/Api Docs-1.10.0-orange.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://docs.justauth.whnb.wang" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
@ -91,7 +91,7 @@ JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.9.6</version>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
|
||||

|
||||
# JustAuth <small>1.9.6</small>
|
||||
# JustAuth <small>1.10.0</small>
|
||||
|
||||
<strong>史上最全的整合第三方登录的开源库</strong>
|
||||
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
## v1.9.6
|
||||
## v1.10.0
|
||||
### 2019/08/06
|
||||
|
||||
- 合并[PR-34](https://github.com/zhangyd-c/JustAuth/pull/34),添加StringUtil单元测试,修复bug
|
||||
- 合并[PR-35](https://github.com/zhangyd-c/JustAuth/pull/35),集成企业微信
|
||||
|
||||
### 2019/08/05
|
||||
|
||||
- 集成华为登录
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.9.6</version>
|
||||
<version>1.10.0</version>
|
||||
|
||||
<name>JustAuth</name>
|
||||
<url>https://gitee.com/yadong.zhang/JustAuth</url>
|
||||
|
||||
@ -4,7 +4,7 @@ package me.zhyd.oauth.cache;
|
||||
* AuthCache配置类
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthCacheConfig {
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ package me.zhyd.oauth.cache;
|
||||
* 默认的state缓存实现
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public enum AuthDefaultStateCache implements AuthStateCache {
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ package me.zhyd.oauth.cache;
|
||||
* </p>
|
||||
*
|
||||
* @author yangkai.shen
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public interface AuthStateCache {
|
||||
/**
|
||||
|
||||
@ -47,7 +47,15 @@ public class AuthConfig {
|
||||
/**
|
||||
* Stack Overflow Key
|
||||
* <p>
|
||||
* 1.9.0版本新增参数
|
||||
*
|
||||
* @since 1.9.0
|
||||
*/
|
||||
private String stackOverflowKey;
|
||||
|
||||
/**
|
||||
* 企业微信,授权方的网页应用ID
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String agentId;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package me.zhyd.oauth.config;
|
||||
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
|
||||
/**
|
||||
* 各api需要的url, 用枚举类分平台类型管理
|
||||
@ -522,7 +522,8 @@ public enum AuthSource {
|
||||
|
||||
/**
|
||||
* 华为
|
||||
* @since 1.9.6
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
HUAWEI {
|
||||
@Override
|
||||
@ -544,6 +545,28 @@ public enum AuthSource {
|
||||
public String refresh() {
|
||||
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 企业微信
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
WECHAT_ENTERPRISE {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://open.work.weixin.qq.com/wwopen/sso/qrConnect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -17,7 +17,7 @@ import java.time.format.DateTimeFormatter;
|
||||
* @see Log#warn(String, Throwable)
|
||||
* @see Log#error(String)
|
||||
* @see Log#error(String, Throwable)
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class Log {
|
||||
|
||||
@ -109,7 +109,7 @@ public class Log {
|
||||
* 日志级别
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@ -134,7 +134,7 @@ public class Log {
|
||||
* 日志配置
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
static class Config {
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ public class AuthCallback {
|
||||
/**
|
||||
* 华为授权登录接受code的参数名
|
||||
*
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String authorization_code;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package me.zhyd.oauth.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ -36,4 +35,11 @@ public class AuthToken {
|
||||
private String macAlgorithm;
|
||||
private String macKey;
|
||||
|
||||
/**
|
||||
* 企业微信附带属性
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
private String code;
|
||||
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import static me.zhyd.oauth.enums.AuthResponseStatus.SUCCESS;
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthHuaweiRequest extends AuthDefaultRequest {
|
||||
|
||||
|
||||
@ -0,0 +1,171 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 企业微信登录
|
||||
* </p>
|
||||
*
|
||||
* @author yangkai.shen (https://xkcoding.com)
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AuthWeChatEnterpriseRequest extends AuthDefaultRequest {
|
||||
public AuthWeChatEnterpriseRequest(AuthConfig config) {
|
||||
super(config, AuthSource.WECHAT_ENTERPRISE);
|
||||
}
|
||||
|
||||
public AuthWeChatEnterpriseRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthSource.WECHAT_ENTERPRISE, authStateCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
|
||||
*
|
||||
* @param authCallback 回调返回的参数
|
||||
* @return 所有信息
|
||||
*/
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
HttpResponse response = doGetAuthorizationCode(accessTokenUrl(authCallback.getCode()));
|
||||
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(object.getString("access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.code(authCallback.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
HttpResponse response = doGetUserInfo(authToken);
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
// 返回 OpenId 或其他,均代表非当前企业用户,不支持
|
||||
if (!object.containsKey("UserId")) {
|
||||
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM);
|
||||
}
|
||||
String userId = object.getString("UserId");
|
||||
HttpResponse userDetailResponse = getUserDetail(authToken.getAccessToken(), userId);
|
||||
JSONObject userDetail = this.checkResponse(userDetailResponse);
|
||||
|
||||
String gender = getRealGender(userDetail);
|
||||
|
||||
return AuthUser.builder()
|
||||
.username(userDetail.getString("name"))
|
||||
.nickname(userDetail.getString("alias"))
|
||||
.avatar(userDetail.getString("avatar"))
|
||||
.location(userDetail.getString("address"))
|
||||
.email(userDetail.getString("email"))
|
||||
.uuid(userId)
|
||||
.gender(AuthUserGender.getRealGender(gender))
|
||||
.token(authToken)
|
||||
.source(source)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验请求结果
|
||||
*
|
||||
* @param response 请求结果
|
||||
* @return 如果请求结果正常,则返回JSONObject
|
||||
*/
|
||||
private JSONObject checkResponse(HttpResponse response) {
|
||||
JSONObject object = JSONObject.parseObject(response.body());
|
||||
|
||||
if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
|
||||
throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的实际性别,0表示未定义,1表示男性,2表示女性
|
||||
*
|
||||
* @param userDetail 用户详情
|
||||
* @return 用户性别
|
||||
*/
|
||||
private String getRealGender(JSONObject userDetail) {
|
||||
int gender = userDetail.getIntValue("gender");
|
||||
if (AuthUserGender.MALE.getCode() == gender) {
|
||||
return "1";
|
||||
}
|
||||
return 2 == gender ? "0" : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
* @since 1.9.3
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("appid", config.getClientId())
|
||||
.queryParam("agentid", config.getAgentId())
|
||||
.queryParam("redirect_uri", config.getRedirectUri())
|
||||
.queryParam("state", getRealState(state))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权码
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.queryParam("corpid", config.getClientId())
|
||||
.queryParam("corpsecret", config.getClientSecret())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取userInfo的url
|
||||
*
|
||||
* @param authToken 用户授权后的token
|
||||
* @return 返回获取userInfo的url
|
||||
*/
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("code", authToken.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户详情
|
||||
*
|
||||
* @param accessToken accessToken
|
||||
* @param userId 企业内用户id
|
||||
* @return 用户详情
|
||||
*/
|
||||
private HttpResponse getUserDetail(String accessToken, String userId) {
|
||||
String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
|
||||
.queryParam("access_token", accessToken)
|
||||
.queryParam("userid", userId)
|
||||
.build();
|
||||
return HttpRequest.get(userDetailUrl).execute();
|
||||
}
|
||||
|
||||
}
|
||||
@ -30,6 +30,9 @@ public class AuthChecker {
|
||||
if (isSupported && AuthSource.STACK_OVERFLOW == source) {
|
||||
isSupported = StringUtils.isNotEmpty(config.getStackOverflowKey());
|
||||
}
|
||||
if (isSupported && AuthSource.WECHAT_ENTERPRISE == source){
|
||||
isSupported = StringUtils.isNotEmpty(config.getAgentId());
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
@ -58,7 +61,7 @@ public class AuthChecker {
|
||||
/**
|
||||
* 校验回调传回的code
|
||||
* <p>
|
||||
* {@code v1.9.6}版本中改为传入{@code source}和{@code callback},对于不同平台使用不同参数接受code的情况统一做处理
|
||||
* {@code v1.10.0}版本中改为传入{@code source}和{@code callback},对于不同平台使用不同参数接受code的情况统一做处理
|
||||
*
|
||||
* @param source 当前授权平台
|
||||
* @param callback 从第三方授权回调回来时传入的参数集合
|
||||
|
||||
@ -8,19 +8,19 @@ import org.junit.Test;
|
||||
/**
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0
|
||||
* @since 1.9.6
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class ThirdPartSdkTest {
|
||||
|
||||
@Test
|
||||
public void huawei() {
|
||||
String code = "CF1IvwdXw18r6LTfoRSgs+LrdP/DuO1VJJmAD0up2grQrSs3gcuyrt1O+jjWp7/TFiBy9IlPepNs/PUggcLe8cgjesqj1+DGXXojJsjEqsokFCCU0eJVt1F02zLDWH1+bq40HSlljXDaTvCBNrqWJJnIZhRetoV9pocrWPLZpYrx/h0iaC9T0GjMRVEXC//LnTAlTjg7";
|
||||
String code = "CF1IwmFc6uZABI9Y795BkhXfvHidIFFw04I4Zc4KML4n+vlXxwNUcQKS4xlopjFDpEk6LzQbjwdTNxvjZ9jqnd/1m5nswhx8X7e0/dL2kyGAMVZWFgVq9ClxNN18b+Z0xtfJjkm7bDnfC3W5h4COgTCoLSjiWKSHWp5hCunp6pQRo1FHovZXm13TLNlhF9mCVtJx3kTQ";
|
||||
HttpResponse response = HttpRequest.post("https://oauth-login.cloud.huawei.com/oauth2/v2/token")
|
||||
.form("grant_type", "authorization_code")
|
||||
.form("code", code)
|
||||
.form("client_id", "100xxxxx")
|
||||
.form("client_secret", "22aea400bef603xxxxxbfb80d")
|
||||
.form("redirect_uri", "http://localhost:8443/huawei/login")
|
||||
.form("client_id", "100994535")
|
||||
.form("client_secret", "22aea400bef603fef26d15a79c806eb477b35de0a529758f2a3b1bda32bfb80d")
|
||||
.form("redirect_uri", "http://127.0.0.1:8443/oauth/callback/huawei")
|
||||
.execute();
|
||||
System.out.println(response.body());
|
||||
|
||||
@ -31,7 +31,7 @@ public class ThirdPartSdkTest {
|
||||
.form("nsp_ts", System.currentTimeMillis())
|
||||
.form("access_token", JSONObject.parseObject(response.body()).getString("access_token"))
|
||||
.form("nsp_fmt", "JS")
|
||||
// .form("nsp_cb", "")
|
||||
// .form("nsp_cb", "_jqjsp")
|
||||
.form("nsp_svc", "OpenUP.User.getInfo")
|
||||
.execute();
|
||||
System.out.println(response2.body());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user