提交 48a368b5 编写于 作者: 智布道's avatar 智布道 👁

合并pr,增加单测以及集成企业微信

......@@ -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
......
![](_media/logo.png)
# JustAuth <small>1.9.6</small>
# JustAuth <small>1.10.0</small>
<strong>史上最全的整合第三方登录的开源库</strong>
......
## 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
- 集成华为登录
......
......@@ -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;
}
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;
}
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 {
......
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());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册