1
0
mirror of synced 2026-04-22 01:18:37 +08:00

📝 集成华为

This commit is contained in:
yadong.zhang
2019-08-05 22:05:58 +08:00
parent 576402eec3
commit 665daa37b2
8 changed files with 300 additions and 3 deletions

View File

@@ -518,6 +518,32 @@ public enum AuthSource {
public String userInfo() {
return "https://api.stackexchange.com/2.2/me";
}
},
/**
* 华为
* @since 1.9.6
*/
HUAWEI {
@Override
public String authorize() {
return "https://oauth-login.cloud.huawei.com/oauth2/v2/authorize";
}
@Override
public String accessToken() {
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
}
@Override
public String userInfo() {
return "https://api.vmall.com/rest.php";
}
@Override
public String refresh() {
return "https://oauth-login.cloud.huawei.com/oauth2/v2/token";
}
};
/**

View File

@@ -27,4 +27,11 @@ public class AuthCallback {
* 访问AuthorizeUrl后回调时带的参数state用于和请求AuthorizeUrl前的state比较防止CSRF攻击
*/
private String state;
/**
* 华为授权登录接受code的参数名
*
* @since 1.9.6
*/
private String authorization_code;
}

View File

@@ -74,7 +74,7 @@ public abstract class AuthDefaultRequest implements AuthRequest {
@Override
public AuthResponse login(AuthCallback authCallback) {
try {
AuthChecker.checkCode(source == AuthSource.ALIPAY ? authCallback.getAuth_code() : authCallback.getCode());
AuthChecker.checkCode(source, authCallback);
this.checkState(authCallback.getState());
AuthToken authToken = this.getAccessToken(authCallback);

View File

@@ -0,0 +1,194 @@
package me.zhyd.oauth.request;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.enums.AuthUserGender;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.utils.UrlBuilder;
import static me.zhyd.oauth.enums.AuthResponseStatus.SUCCESS;
/**
* 华为授权登录
*
* @author yadong.zhang (yadong.zhang0415(a)gmail.com)
* @version 1.0
* @since 1.9.6
*/
public class AuthHuaweiRequest extends AuthDefaultRequest {
public AuthHuaweiRequest(AuthConfig config) {
super(config, AuthSource.HUAWEI);
}
public AuthHuaweiRequest(AuthConfig config, AuthStateCache authStateCache) {
super(config, AuthSource.HUAWEI, authStateCache);
}
/**
* 获取access token
*
* @param authCallback 授权成功后的回调参数
* @return token
* @see AuthDefaultRequest#authorize()
* @see AuthDefaultRequest#authorize(String)
*/
@Override
protected AuthToken getAccessToken(AuthCallback authCallback) {
HttpRequest request = HttpRequest.post(source.accessToken())
.form("grant_type", "authorization_code")
.form("code", authCallback.getAuthorization_code())
.form("client_id", config.getClientId())
.form("client_secret", config.getClientSecret())
.form("redirect_uri", config.getRedirectUri());
return getAuthToken(request);
}
/**
* 使用token换取用户信息
*
* @param authToken token信息
* @return 用户信息
* @see AuthDefaultRequest#getAccessToken(AuthCallback)
*/
@Override
protected AuthUser getUserInfo(AuthToken authToken) {
HttpResponse response = HttpRequest.post(source.userInfo())
.form("nsp_ts", System.currentTimeMillis())
.form("access_token", authToken.getAccessToken())
.form("nsp_fmt", "JS")
.form("nsp_svc", "OpenUP.User.getInfo")
.execute();
JSONObject object = JSONObject.parseObject(response.body());
this.checkResponse(object);
AuthUserGender gender = getRealGender(object);
return AuthUser.builder()
.uuid(object.getString("userID"))
.username(object.getString("userName"))
.nickname(object.getString("userName"))
.gender(gender)
.avatar(object.getString("headPictureURL"))
.build();
}
/**
* 刷新access token (续期)
*
* @param authToken 登录成功后返回的Token信息
* @return AuthResponse
*/
@Override
public AuthResponse refresh(AuthToken authToken) {
HttpRequest request = HttpRequest.post(source.refresh())
.form("client_id", config.getClientId())
.form("client_secret", config.getClientSecret())
.form("refresh_token", authToken.getRefreshToken())
.form("grant_type", "refresh_token");
return AuthResponse.builder()
.code(SUCCESS.getCode())
.data(getAuthToken(request))
.build();
}
private AuthToken getAuthToken(HttpRequest request) {
HttpResponse response = request.execute();
JSONObject object = JSONObject.parseObject(response.body());
this.checkResponse(object);
return AuthToken.builder()
.accessToken(object.getString("access_token"))
.expireIn(object.getIntValue("expires_in"))
.refreshToken(object.getString("refresh_token"))
.build();
}
/**
* 返回带{@code state}参数的授权url授权回调时会带上这个{@code state}
*
* @param state state 验证授权流程的参数可以防止csrf
* @return 返回授权地址
* @since 1.9.3
*/
@Override
public String authorize(String state) {
return UrlBuilder.fromBaseUrl(source.authorize())
.queryParam("response_type", "code")
.queryParam("client_id", config.getClientId())
.queryParam("redirect_uri", config.getRedirectUri())
.queryParam("access_type", "offline")
.queryParam("scope", "https%3A%2F%2Fwww.huawei.com%2Fauth%2Faccount%2Fbase.profile")
.queryParam("state", getRealState(state))
.build();
}
/**
* 返回获取accessToken的url
*
* @param code 授权码
* @return 返回获取accessToken的url
*/
@Override
protected String accessTokenUrl(String code) {
return UrlBuilder.fromBaseUrl(source.accessToken())
.queryParam("grant_type", "authorization_code")
.queryParam("code", code)
.queryParam("client_id", config.getClientId())
.queryParam("client_secret", config.getClientSecret())
.queryParam("redirect_uri", config.getRedirectUri())
.build();
}
/**
* 返回获取userInfo的url
*
* @param authToken token
* @return 返回获取userInfo的url
*/
@Override
protected String userInfoUrl(AuthToken authToken) {
return UrlBuilder.fromBaseUrl(source.userInfo())
.queryParam("nsp_ts", System.currentTimeMillis())
.queryParam("access_token", authToken.getAccessToken())
.queryParam("nsp_fmt", "JS")
.queryParam("nsp_svc", "OpenUP.User.getInfo")
.build();
}
/**
* 获取用户的实际性别。华为系统中用户的性别1表示女0表示男
*
* @param object obj
* @return AuthUserGender
*/
private AuthUserGender getRealGender(JSONObject object) {
int genderCodeInt = object.getIntValue("gender");
String genderCode = genderCodeInt == 1 ? "0" : (genderCodeInt == 0) ? "1" : genderCodeInt + "";
return AuthUserGender.getRealGender(genderCode);
}
/**
* 校验响应结果
*
* @param object 接口返回的结果
*/
private void checkResponse(JSONObject object) {
if (object.containsKey("error")) {
if (!object.containsKey("sub_error") && !object.containsKey("error_description")) {
throw new AuthException(object.getString("error"));
}
throw new AuthException(object.getString("sub_error") + ":" + object.getString("error_description"));
}
}
}

View File

@@ -4,6 +4,7 @@ import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.enums.AuthResponseStatus;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
/**
* 授权配置类的校验器
@@ -56,11 +57,20 @@ public class AuthChecker {
/**
* 校验回调传回的code
* <p>
* {@code v1.9.6}版本中改为传入{@code source}和{@code callback}对于不同平台使用不同参数接受code的情况统一做处理
*
* @param code 回调时传回的code
* @param source 当前授权平台
* @param callback 从第三方授权回调回来时传入的参数集合
* @since 1.8.0
*/
public static void checkCode(String code) {
public static void checkCode(AuthSource source, AuthCallback callback) {
String code = callback.getCode();
if (source == AuthSource.ALIPAY) {
code = callback.getAuth_code();
} else if (source == AuthSource.HUAWEI) {
code = callback.getAuthorization_code();
}
if (StringUtils.isEmpty(code)) {
throw new AuthException(AuthResponseStatus.ILLEGAL_CODE);
}