SocialSignOn

This commit is contained in:
MaxKey 2022-01-23 18:18:06 +08:00
parent 6e392b5e1f
commit b56496a6df
6 changed files with 258 additions and 6 deletions

View File

@ -0,0 +1,172 @@
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.enums.AuthUserGender;
import me.zhyd.oauth.enums.scope.AuthHuaweiScope;
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.HashMap;
import java.util.Map;
import static me.zhyd.oauth.enums.AuthResponseStatus.SUCCESS;
public class AuthHuaweiWeLinkRequest extends AuthDefaultRequest {
public AuthHuaweiWeLinkRequest(AuthConfig config) {
super(config, WeLinkAuthDefaultSource.HUAWEI_WELINK);
}
public AuthHuaweiWeLinkRequest(AuthConfig config, AuthStateCache authStateCache) {
super(config, WeLinkAuthDefaultSource.HUAWEI_WELINK, authStateCache);
}
/**
* 获取access token
*
* @param authCallback 授权成功后的回调参数
* @return token
* @see AuthDefaultRequest#authorize()
* @see AuthDefaultRequest#authorize(String)
*/
@Override
protected AuthToken getAccessToken(AuthCallback authCallback) {
Map<String, String> form = new HashMap<>(8);
form.put("grant_type", "authorization_code");
form.put("code", authCallback.getAuthorization_code());
form.put("client_id", config.getClientId());
form.put("client_secret", config.getClientSecret());
form.put("redirect_uri", config.getRedirectUri());
String response = new HttpUtils(config.getHttpConfig()).post(source.accessToken(), form, false).getBody();
return getAuthToken(response);
}
/**
* 使用token换取用户信息
*
* @param authToken token信息
* @return 用户信息
* @see AuthDefaultRequest#getAccessToken(AuthCallback)
*/
@Override
protected AuthUser getUserInfo(AuthToken authToken) {
Map<String, String> form = new HashMap<>(7);
form.put("nsp_ts", System.currentTimeMillis() + "");
form.put("access_token", authToken.getAccessToken());
form.put("nsp_fmt", "JS");
form.put("nsp_svc", "OpenUP.User.getInfo");
String response = new HttpUtils(config.getHttpConfig()).post(source.userInfo(), form, false).getBody();
JSONObject object = JSONObject.parseObject(response);
this.checkResponse(object);
AuthUserGender gender = getRealGender(object);
return AuthUser.builder()
.rawUserInfo(object)
.uuid(object.getString("userId"))
.username(object.getString("userNameCn"))
.nickname(object.getString("userNameCn"))
.gender(gender)
//.avatar(object.getString("headPictureURL"))
.token(authToken)
.source(source.toString())
.build();
}
/**
* 刷新access token 续期
*
* @param authToken 登录成功后返回的Token信息
* @return AuthResponse
*/
@Override
public AuthResponse refresh(AuthToken authToken) {
Map<String, String> form = new HashMap<>(7);
form.put("client_id", config.getClientId());
form.put("client_secret", config.getClientSecret());
form.put("refresh_token", authToken.getRefreshToken());
form.put("grant_type", "refresh_token");
String response = new HttpUtils(config.getHttpConfig()).post(source.refresh(), form, false).getBody();
return AuthResponse.builder().code(SUCCESS.getCode()).data(getAuthToken(response)).build();
}
private AuthToken getAuthToken(String response) {
JSONObject object = JSONObject.parseObject(response);
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(super.authorize(state))
.queryParam("access_type", "offline")
.queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthHuaweiScope.values())))
.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("NSP_STATUS")) {
throw new AuthException(object.getString("error"));
}
if (object.containsKey("error")) {
throw new AuthException(object.getString("sub_error") + ":" + object.getString("error_description"));
}
}
}

View File

@ -0,0 +1,33 @@
package me.zhyd.oauth.request;
import me.zhyd.oauth.config.AuthSource;
public enum WeLinkAuthDefaultSource implements AuthSource{
HUAWEI_WELINK {
@Override
public String authorize() {
return "https://login.welink.huaweicloud.com/connect/oauth2/sns_authorize";
}
@Override
public String accessToken() {
return "https://open.welink.huaweicloud.com/api/auth/v2/tickets";
}
@Override
public String userInfo() {
return "https://open.welink.huaweicloud.com/api/contact/v1/users";
}
@Override
public String refresh() {
return "";
}
@Override
public Class<? extends AuthDefaultRequest> getTargetClass() {
return AuthHuaweiWeLinkRequest.class;
}
}
}

View File

@ -123,8 +123,12 @@ public class SocialSignOnProviderService{
authRequest = new AuthWeChatEnterpriseQrcodeRequest(authConfig);
}else if(provider.equalsIgnoreCase("workweixin")) {
authRequest = new AuthWeChatEnterpriseWebRequest(authConfig);
}else if(provider.equalsIgnoreCase("welink")) {
authRequest = new AuthHuaweiWeLinkRequest(authConfig);
}
return authRequest;
}

View File

@ -21,39 +21,53 @@ public class ResponseData {
protected long errcode;
protected long code;
protected String errmsg;
protected String msg;
protected String message;
public long getErrcode() {
return errcode;
}
public void setErrcode(long errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ResponseData() {
super();
}
}

View File

@ -86,6 +86,9 @@
<#if sspLogin.dingTalkLogin != 'none'>
<#include "loginscandingtalk.ftl">
</#if>
<#if sspLogin.weLinkLogin != 'none'>
<#include "loginscanwelink.ftl">
</#if>
</div>
</td>
</tr>

View File

@ -0,0 +1,26 @@
<#if sspLogin.weLinkLogin == 'https'>
<script src="https://login.welink.huaweicloud.com/sso-proxy-front/public/qrcode/0.0.1/wlQrcodeLogin.js"></script>
</#if>
<#if sspLogin.weLinkLogin == 'http'>
<script src="http://login.welink.huaweicloud.com/sso-proxy-front/public/qrcode/0.0.1/wlQrcodeLogin.js"></script>
</#if>
<script type="text/javascript">
$(function(){
$("#qrcodelogin").on("click",function(){
$.get("<@base />/logon/oauth20/scanqrcode/welink",function(data,status){
var wlqrcodeLogin = wlQrcodeLogin({
id:"div_qrcodelogin",//这里需要你在自己的页面定义一个HTML标签并设置id例如<div id="login_container"></div>或<span id="login_container"></span>
client_id: data.clientId,
response_type: "code",
scope: "snsapi_login",
state: data.state,
redirect_uri: encodeURIComponent(data.redirectUri),
style: "border:none;background-color:#FFFFFF;",
width : "365",
height: "400",
self_redirect: false});
$('#div_qrcodelogin').show();
});
});
});
</script>