mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-12 07:25:39 +08:00
feat(social): 新增Google OAuth2三方登录对接(平台枚举/GoogleRequest/工厂分支/i18n)
This commit is contained in:
@@ -5,6 +5,7 @@ import cn.daxpay.open.platform.capability.social.justauth.request.DouyinRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.FeishuRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.GithubRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.GiteeRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.GoogleRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.QqRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.SocialAuthRequest;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.request.WeComRequest;
|
||||
@@ -27,6 +28,7 @@ public class SocialAuthRequestFactory {
|
||||
return switch (source) {
|
||||
case GITHUB -> new GithubRequest(config);
|
||||
case GITEE -> new GiteeRequest(config);
|
||||
case GOOGLE -> new GoogleRequest(config);
|
||||
case QQ -> new QqRequest(config);
|
||||
case WECHAT_MP -> new WechatMpRequest(config);
|
||||
case WE_COM -> new WeComRequest(config);
|
||||
|
||||
@@ -80,6 +80,14 @@ public enum SocialSourceEnum implements I18nSupport {
|
||||
"https://gitee.com/api/v5/user"
|
||||
),
|
||||
|
||||
/// Google
|
||||
GOOGLE(
|
||||
"google",
|
||||
"https://accounts.google.com/o/oauth2/v2/auth",
|
||||
"https://oauth2.googleapis.com/token",
|
||||
"https://openidconnect.googleapis.com/v1/userinfo"
|
||||
),
|
||||
|
||||
;
|
||||
|
||||
/// 平台编码(与 AuthLoginTypeCode 对应, 作为配置和绑定的唯一标识)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package cn.daxpay.open.platform.capability.social.justauth.request;
|
||||
|
||||
import cn.daxpay.open.platform.capability.social.justauth.SocialAuthConfig;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.SocialSourceEnum;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.exception.SocialException;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.model.AuthCallback;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.model.AuthToken;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.model.AuthUser;
|
||||
import cn.daxpay.open.platform.capability.social.justauth.util.SocialUrlBuilder;
|
||||
import cn.hutool.json.JSONObject;
|
||||
|
||||
/// # Google 授权登录
|
||||
///
|
||||
/// [Google OAuth2.0 / OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect)
|
||||
/// authorize 必须显式携带 scope(openid email profile), 否则无法获取用户信息;
|
||||
/// token 响应为 JSON, 用户信息接口需通过 Authorization: Bearer 头携带令牌,
|
||||
/// 用户唯一标识为 sub 字段.
|
||||
///
|
||||
public class GoogleRequest extends AbstractSocialAuthRequest {
|
||||
|
||||
public GoogleRequest(SocialAuthConfig config) {
|
||||
super(config, SocialSourceEnum.GOOGLE);
|
||||
}
|
||||
|
||||
/// Google 授权地址必须显式声明 scope(openid email profile)
|
||||
/// 默认通用 authorize 方法不带 scope, 故在此重写
|
||||
@Override
|
||||
public String authorize(String state) {
|
||||
return SocialUrlBuilder.ofBaseUrl(this.getSource().authorize())
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("client_id", this.getConfig().getClientId())
|
||||
.queryParam("redirect_uri", this.buildRedirectUri())
|
||||
.queryParam("state", state)
|
||||
.queryParam("scope", "openid email profile")
|
||||
.build();
|
||||
}
|
||||
|
||||
/// Google 的 token 响应为 JSON 格式
|
||||
@Override
|
||||
public AuthToken getAccessToken(AuthCallback callback) {
|
||||
String response = this.doPost(this.accessTokenUrl(callback.getCode()));
|
||||
JSONObject object = this.parseObj(response);
|
||||
if (object.containsKey("error")) {
|
||||
throw new SocialException(object.getStr("error_description"));
|
||||
}
|
||||
return new AuthToken()
|
||||
.setAccessToken(object.getStr("access_token"))
|
||||
.setRefreshToken(object.getStr("refresh_token"))
|
||||
.setScope(object.getStr("scope"))
|
||||
.setTokenType(object.getStr("token_type"))
|
||||
.setExpireIn(object.getInt("expires_in", 0));
|
||||
}
|
||||
|
||||
/// Google 用户信息需通过 Authorization: Bearer 头携带令牌
|
||||
/// 唯一标识为 sub, 昵称取 name, 头像取 picture, 邮箱取 email
|
||||
@Override
|
||||
public AuthUser getUserInfo(AuthToken token) {
|
||||
String response = this.doGet(
|
||||
this.getSource().userInfo(),
|
||||
this.headers("Authorization", "Bearer " + token.getAccessToken())
|
||||
);
|
||||
JSONObject object = this.parseObj(response);
|
||||
if (object.containsKey("error")) {
|
||||
throw new SocialException(object.getStr("error_description"));
|
||||
}
|
||||
return new AuthUser()
|
||||
.setUuid(object.getStr("sub"))
|
||||
.setUsername(object.getStr("email"))
|
||||
.setNickname(object.getStr("name"))
|
||||
.setAvatar(object.getStr("picture"))
|
||||
.setEmail(object.getStr("email"))
|
||||
.setSource(this.getSourceName())
|
||||
.setToken(token);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
"qq": "QQ",
|
||||
"github": "GitHub",
|
||||
"gitee": "Gitee",
|
||||
"google": "Google",
|
||||
"feishu": "Feishu",
|
||||
"dingTalk": "DingTalk",
|
||||
"douyin": "Douyin"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"qq": "QQ",
|
||||
"github": "GitHub",
|
||||
"gitee": "Gitee",
|
||||
"google": "Google",
|
||||
"feishu": "飞书",
|
||||
"dingTalk": "钉钉",
|
||||
"douyin": "抖音"
|
||||
|
||||
Reference in New Issue
Block a user