Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af8fda700b | ||
|
|
881a87ed95 | ||
|
|
4c8fdbae49 | ||
|
|
e8db2dd282 | ||
|
|
90374762e4 | ||
|
|
e5d44e91b8 | ||
|
|
41559fc954 | ||
|
|
d354278e7d | ||
|
|
c2d6661a76 | ||
|
|
5ee87760be |
@@ -1,3 +1,15 @@
|
||||
## 1.16.2
|
||||
|
||||
### 2021/7/28
|
||||
|
||||
- 发布 v1.16.2
|
||||
- 新增
|
||||
- 集成“程序员客栈”平台登录
|
||||
- 修改
|
||||
- 更新文档
|
||||
- 修复“淘宝”平台授权登录后没有`uid`的问题、增加刷新token的功能
|
||||
- 修复“Twitter”平台授权登录后获取不到用户邮箱的问题
|
||||
|
||||
## 1.16.1
|
||||
|
||||
### 2021/4/19
|
||||
|
||||
@@ -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%20Central-1.16.1-blue" ></img>
|
||||
<img src="https://img.shields.io/github/v/release/justauth/JustAuth?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>
|
||||
@@ -14,9 +14,6 @@
|
||||
<a target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api%20Docs-1.16.1-orange" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://justauth.wiki" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
@@ -59,7 +56,7 @@ These artifacts are available from Maven Central:
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.16.2</version>
|
||||
</dependency>
|
||||
```
|
||||
- Using JustAuth
|
||||
|
||||
21
README.md
21
README.md
@@ -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%20Central-1.16.1-blue" ></img>
|
||||
<img src="https://img.shields.io/github/v/release/justauth/JustAuth?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>
|
||||
@@ -14,9 +14,6 @@
|
||||
<a target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://apidoc.gitee.com/yadong.zhang/JustAuth/" title="API文档">
|
||||
<img src="https://img.shields.io/badge/Api%20Docs-1.16.1-orange" ></img>
|
||||
</a>
|
||||
<a target="_blank" href="https://justauth.wiki" title="参考文档">
|
||||
<img src="https://img.shields.io/badge/Docs-latest-blueviolet.svg" ></img>
|
||||
</a>
|
||||
@@ -69,7 +66,7 @@ JustAuth 集成了诸如:Github、Gitee、支付宝、新浪微博、微信、
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.16.2</version>
|
||||
</dependency>
|
||||
```
|
||||
- 调用api
|
||||
@@ -123,7 +120,7 @@ authRequest.login(callback);
|
||||
|
||||
感谢以下赞助商的支持:
|
||||
|
||||
<a href="https://www.duohui.cn?utm_source=justauth" target="_blank"><img src="https://docs.duohui.cn/brand_source/img/std.svg" alt="多会 - 专业活动管理系统" style="height: 54px;" height="54px" /></a>
|
||||
[我要赞助](https://justauth.wiki/sponsor.html)
|
||||
|
||||
## JustAuth 的用户
|
||||
有很多公司、组织和个人把 JustAuth 用于学习、研究、生产环境和商业产品中,包括(但不限于):
|
||||
@@ -133,20 +130,24 @@ authRequest.login(callback);
|
||||
怎么没有我?[登记](https://gitee.com/yadong.zhang/JustAuth/issues/IZ2T7)
|
||||
|
||||
## 开源推荐
|
||||
|
||||
- `JAP` 开源的登录认证中间件: [https://gitee.com/fujieid/jap](https://gitee.com/fujieid/jap)
|
||||
- `spring-boot-demo` 深度学习并实战 spring boot 的项目: [https://github.com/xkcoding/spring-boot-demo](https://github.com/xkcoding/spring-boot-demo)
|
||||
- `mica` SpringBoot 微服务高效开发工具集: [https://github.com/lets-mica/mica](https://github.com/lets-mica/mica)
|
||||
- `pig` 微服务认证授权脚手架(架构师必备): [https://gitee.com/log4j/pig](https://gitee.com/log4j/pig)
|
||||
- `SpringBlade` 完整的线上解决方案(企业开发必备): [https://gitee.com/smallc/SpringBlade](https://gitee.com/smallc/SpringBlade)
|
||||
- `MaxKey` 马克思的钥匙,寓意是最大钥匙,是用户单点登录认证系统(Sigle Sign On System),OAuth 2.0/OpenID Connect、SAML 2.0、JWT、CAS等标准化的开放协议,使用JustAuth集成OAuth第三方认证。: [https://shimingxy.github.io/MaxKey/](https://shimingxy.github.io/MaxKey/)
|
||||
- `YurunOAuthLogin` PHP 第三方登录授权 SDK:[YurunOAuthLogin](https://gitee.com/yurunsoft/YurunOAuthLogin)
|
||||
- `sureness` 面向restful api的高性能认证鉴权框架:[sureness](https://github.com/usthe/sureness)
|
||||
|
||||
更多推荐,请参考:[JustAuth - 开源推荐](https://justauth.wiki)
|
||||
|
||||
## 鸣谢
|
||||
|
||||
- 感谢 JetBrains 提供的免费开源 License:
|
||||
|
||||
<p>
|
||||
<img src="https://images.gitee.com/uploads/images/2020/0406/220236_f5275c90_5531506.png" alt="图片引用自lets-mica" style="float:left;">
|
||||
</p>
|
||||
|
||||
## 其他
|
||||
|
||||
- [CONTRIBUTORS](https://justauth.wiki/contributors.html)
|
||||
- [CHANGELOGS](https://justauth.wiki/update.html)
|
||||
- [PLAN](https://gitee.com/yadong.zhang/JustAuth/issues/IUGRK)
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.16.1
|
||||
1.16.2
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.16.2</version>
|
||||
|
||||
<name>JustAuth</name>
|
||||
<url>https://gitee.com/yadong.zhang/JustAuth</url>
|
||||
|
||||
@@ -744,7 +744,7 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://api.twitter.com/1.1/users/show.json";
|
||||
return "https://api.twitter.com/1.1/account/verify_credentials.json";
|
||||
}
|
||||
},
|
||||
|
||||
@@ -976,4 +976,25 @@ public enum AuthDefaultSource implements AuthSource {
|
||||
return "https://%s.okta.com/oauth2/%s/v1/revoke";
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 程序员客栈
|
||||
*
|
||||
* @since 1.16.2
|
||||
*/
|
||||
PROGINN {
|
||||
@Override
|
||||
public String authorize() {
|
||||
return "https://www.proginn.com/oauth2/authorize";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String accessToken() {
|
||||
return "https://www.proginn.com/oauth2/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userInfo() {
|
||||
return "https://www.proginn.com/openapi/user/basic_info";
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package me.zhyd.oauth.enums.scope;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Gitee 平台 OAuth 授权范围
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @version 1.0.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AuthProginnScope implements AuthScope {
|
||||
|
||||
/**
|
||||
* {@code scope} 含义,以{@code description} 为准
|
||||
*/
|
||||
BASIC("basic", "访问用户的基本信息", true),
|
||||
/**
|
||||
* 以上 scope 需要单独向程序员客栈平台申请,否则不可使用
|
||||
*/
|
||||
email("email", "获取用户的邮箱", false),
|
||||
realname("realname", "获取用户的真实姓名", false),
|
||||
cellphone("cellphone", "获取用户的手机号码", false),
|
||||
;
|
||||
|
||||
private final String scope;
|
||||
private final String description;
|
||||
private final boolean isDefault;
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
String response = doGetAuthorizationCode(accessTokenUrl(authCallback.getCode()));
|
||||
String response = doGetAuthorizationCode(accessTokenUrl(null));
|
||||
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
|
||||
97
src/main/java/me/zhyd/oauth/request/AuthProginnRequest.java
Normal file
97
src/main/java/me/zhyd/oauth/request/AuthProginnRequest.java
Normal file
@@ -0,0 +1,97 @@
|
||||
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.enums.scope.AuthProginnScope;
|
||||
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.AuthScopeUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 程序员客栈
|
||||
*
|
||||
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
|
||||
* @since 1.16.2
|
||||
*/
|
||||
public class AuthProginnRequest extends AuthDefaultRequest {
|
||||
|
||||
public AuthProginnRequest(AuthConfig config) {
|
||||
super(config, AuthDefaultSource.PROGINN);
|
||||
}
|
||||
|
||||
public AuthProginnRequest(AuthConfig config, AuthStateCache authStateCache) {
|
||||
super(config, AuthDefaultSource.PROGINN, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("code", authCallback.getCode());
|
||||
params.put("client_id", config.getClientId());
|
||||
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);
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
this.checkResponse(accessTokenObject);
|
||||
return AuthToken.builder()
|
||||
.accessToken(accessTokenObject.getString("access_token"))
|
||||
.refreshToken(accessTokenObject.getString("refresh_token"))
|
||||
.uid(accessTokenObject.getString("uid"))
|
||||
.tokenType(accessTokenObject.getString("token_type"))
|
||||
.expireIn(accessTokenObject.getIntValue("expires_in"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String userInfo = doGetUserInfo(authToken);
|
||||
JSONObject object = JSONObject.parseObject(userInfo);
|
||||
this.checkResponse(object);
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(object)
|
||||
.uuid(object.getString("uid"))
|
||||
.username(object.getString("nickname"))
|
||||
.nickname(object.getString("nickname"))
|
||||
.avatar(object.getString("avatar"))
|
||||
.email(object.getString("email"))
|
||||
.gender(AuthUserGender.UNKNOWN)
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查响应内容是否正确
|
||||
*
|
||||
* @param object 请求响应内容
|
||||
*/
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
* @param state state 验证授权流程的参数,可以防止csrf
|
||||
* @return 返回授权地址
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return UrlBuilder.fromBaseUrl(super.authorize(state))
|
||||
.queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthProginnScope.values())))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,16 @@ 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.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
@@ -33,6 +37,26 @@ public class AuthTaobaoRequest extends AuthDefaultRequest {
|
||||
return AuthToken.builder().accessCode(authCallback.getCode()).build();
|
||||
}
|
||||
|
||||
private AuthToken getAuthToken(JSONObject object) {
|
||||
this.checkResponse(object);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(object.getString("access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.tokenType(object.getString("token_type"))
|
||||
.idToken(object.getString("id_token"))
|
||||
.refreshToken(object.getString("refresh_token"))
|
||||
.uid(object.getString("taobao_user_id"))
|
||||
.openId(object.getString("taobao_open_uid"))
|
||||
.build();
|
||||
}
|
||||
|
||||
private void checkResponse(JSONObject object) {
|
||||
if (object.containsKey("error")) {
|
||||
throw new AuthException(object.getString("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
String response = doPostAuthorizationCode(authToken.getAccessCode());
|
||||
@@ -40,16 +64,12 @@ public class AuthTaobaoRequest extends AuthDefaultRequest {
|
||||
if (accessTokenObject.containsKey("error")) {
|
||||
throw new AuthException(accessTokenObject.getString("error_description"));
|
||||
}
|
||||
authToken.setAccessToken(accessTokenObject.getString("access_token"));
|
||||
authToken.setRefreshToken(accessTokenObject.getString("refresh_token"));
|
||||
authToken.setExpireIn(accessTokenObject.getIntValue("expires_in"));
|
||||
authToken.setUid(accessTokenObject.getString("taobao_user_id"));
|
||||
authToken.setOpenId(accessTokenObject.getString("taobao_open_uid"));
|
||||
authToken = this.getAuthToken(accessTokenObject);
|
||||
|
||||
String nick = GlobalAuthUtils.urlDecode(accessTokenObject.getString("taobao_user_nick"));
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(new JSONObject())
|
||||
.uuid(accessTokenObject.getString("taobao_user_id"))
|
||||
.rawUserInfo(accessTokenObject)
|
||||
.uuid(StringUtils.isEmpty(authToken.getUid()) ? authToken.getOpenId() : authToken.getUid())
|
||||
.username(nick)
|
||||
.nickname(nick)
|
||||
.gender(AuthUserGender.UNKNOWN)
|
||||
@@ -58,6 +78,17 @@ public class AuthTaobaoRequest extends AuthDefaultRequest {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse refresh(AuthToken oldToken) {
|
||||
String tokenUrl = refreshTokenUrl(oldToken.getRefreshToken());
|
||||
String response = new HttpUtils(config.getHttpConfig()).post(tokenUrl);
|
||||
JSONObject accessTokenObject = JSONObject.parseObject(response);
|
||||
return AuthResponse.builder()
|
||||
.code(AuthResponseStatus.SUCCESS.getCode())
|
||||
.data(this.getAuthToken(accessTokenObject))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state}
|
||||
*
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import com.xkcoding.http.constants.Constants;
|
||||
import com.xkcoding.http.support.HttpHeader;
|
||||
import com.xkcoding.http.util.MapUtil;
|
||||
@@ -11,6 +10,7 @@ import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.GlobalAuthUtils;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -47,7 +47,7 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
*/
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
AuthToken token = this.getRequestToken();
|
||||
AuthToken token = this.getRequestToken();
|
||||
return UrlBuilder.fromBaseUrl(source.authorize())
|
||||
.queryParam("oauth_token", token.getOauthToken())
|
||||
.build();
|
||||
@@ -119,17 +119,15 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
@Override
|
||||
protected AuthUser getUserInfo(AuthToken authToken) {
|
||||
Map<String, String> queryParams = new HashMap<>(5);
|
||||
queryParams.put("user_id", authToken.getUserId());
|
||||
queryParams.put("screen_name", authToken.getScreenName());
|
||||
queryParams.put("include_entities", Boolean.toString(true));
|
||||
queryParams.put("include_email", Boolean.toString(true));
|
||||
|
||||
Map<String, String> oauthParams = buildOauthParams();
|
||||
oauthParams.put("oauth_token", authToken.getOauthToken());
|
||||
|
||||
Map<String, String> params = new HashMap<>(oauthParams);
|
||||
params.putAll(queryParams);
|
||||
oauthParams.put("oauth_signature", generateTwitterSignature(params, "GET", source.userInfo(), config.getClientSecret(), authToken
|
||||
.getOauthTokenSecret()));
|
||||
oauthParams.put("oauth_signature", generateTwitterSignature(params, "GET", source.userInfo(), config.getClientSecret(), authToken.getOauthTokenSecret()));
|
||||
String header = buildHeader(oauthParams);
|
||||
|
||||
HttpHeader httpHeader = new HttpHeader();
|
||||
@@ -147,6 +145,7 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
.blog(userInfo.getString("url"))
|
||||
.location(userInfo.getString("location"))
|
||||
.avatar(userInfo.getString("profile_image_url"))
|
||||
.email(userInfo.getString("email"))
|
||||
.source(source.toString())
|
||||
.token(authToken)
|
||||
.build();
|
||||
@@ -155,9 +154,8 @@ public class AuthTwitterRequest extends AuthDefaultRequest {
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("user_id", authToken.getUserId())
|
||||
.queryParam("screen_name", authToken.getScreenName())
|
||||
.queryParam("include_entities", true)
|
||||
.queryParam("include_email", true)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user