From d24733e016026be23758cd18b5b9f617e39b7323 Mon Sep 17 00:00:00 2001 From: "Yangkai.Shen" <237497819@qq.com> Date: Tue, 21 May 2019 15:09:16 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81Google=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/AuthorizationFactory.java | 1 + .../authorization/GoogleAuthorization.java | 19 ++++++ .../java/me/zhyd/oauth/consts/ApiUrl.java | 29 +++++++++ .../java/me/zhyd/oauth/model/AuthSource.java | 3 + .../java/me/zhyd/oauth/model/AuthToken.java | 8 +++ .../zhyd/oauth/request/AuthGoogleRequest.java | 63 +++++++++++++++++++ .../java/me/zhyd/oauth/utils/UrlBuilder.java | 38 +++++++++++ .../java/me/zhyd/oauth/AuthRequestTest.java | 13 ++++ 8 files changed, 174 insertions(+) create mode 100644 src/main/java/me/zhyd/oauth/authorization/GoogleAuthorization.java create mode 100644 src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java diff --git a/src/main/java/me/zhyd/oauth/authorization/AuthorizationFactory.java b/src/main/java/me/zhyd/oauth/authorization/AuthorizationFactory.java index 7d2c65c..3868917 100644 --- a/src/main/java/me/zhyd/oauth/authorization/AuthorizationFactory.java +++ b/src/main/java/me/zhyd/oauth/authorization/AuthorizationFactory.java @@ -59,6 +59,7 @@ public class AuthorizationFactory { AuthorizationFactory.register(AuthSource.DINGTALK, new DingTalkAuthorization()); AuthorizationFactory.register(AuthSource.GITEE, new GiteeAuthorization()); AuthorizationFactory.register(AuthSource.GITHUB, new GithubAuthorization()); + AuthorizationFactory.register(AuthSource.GOOGLE, new GoogleAuthorization()); AuthorizationFactory.register(AuthSource.OSCHINA, new OschinaAuthorization()); AuthorizationFactory.register(AuthSource.QQ, new QqAuthorization()); AuthorizationFactory.register(AuthSource.TAOBAO, new TaobaoAuthorization()); diff --git a/src/main/java/me/zhyd/oauth/authorization/GoogleAuthorization.java b/src/main/java/me/zhyd/oauth/authorization/GoogleAuthorization.java new file mode 100644 index 0000000..6a6b318 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/authorization/GoogleAuthorization.java @@ -0,0 +1,19 @@ +package me.zhyd.oauth.authorization; + +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + * Google授权 + * + * @author yangkai.shen (https://xkcoding.com) + * @version 1.3 + * @since 1.3 + */ +public class GoogleAuthorization implements Authorization { + + @Override + public String getAuthorizeUrl(AuthConfig config) { + return UrlBuilder.getGoogleAuthorizeUrl(config.getClientId(), config.getRedirectUri()); + } +} diff --git a/src/main/java/me/zhyd/oauth/consts/ApiUrl.java b/src/main/java/me/zhyd/oauth/consts/ApiUrl.java index a99eb02..377475f 100644 --- a/src/main/java/me/zhyd/oauth/consts/ApiUrl.java +++ b/src/main/java/me/zhyd/oauth/consts/ApiUrl.java @@ -383,6 +383,35 @@ public enum ApiUrl { throw new AuthException(ResponseStatus.UNSUPPORTED); } + @Override + public String refresh() { + throw new AuthException(ResponseStatus.UNSUPPORTED); + } + }, + /** + * Google + */ + GOOGLE { + @Override + public String authorize() { + return "https://accounts.google.com/o/oauth2/v2/auth"; + } + + @Override + public String accessToken() { + return "https://www.googleapis.com/oauth2/v4/token"; + } + + @Override + public String userInfo() { + return "https://oauth2.googleapis.com/tokeninfo"; + } + + @Override + public String revoke() { + throw new AuthException(ResponseStatus.UNSUPPORTED); + } + @Override public String refresh() { throw new AuthException(ResponseStatus.UNSUPPORTED); diff --git a/src/main/java/me/zhyd/oauth/model/AuthSource.java b/src/main/java/me/zhyd/oauth/model/AuthSource.java index 55631b6..f4f964d 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/model/AuthSource.java @@ -21,5 +21,8 @@ public enum AuthSource { TAOBAO, QQ, WECHAT, + /** + * 谷歌登录,参考文档:https://developers.google.com/identity/protocols/OpenIDConnect + */ GOOGLE, } diff --git a/src/main/java/me/zhyd/oauth/model/AuthToken.java b/src/main/java/me/zhyd/oauth/model/AuthToken.java index 011ece8..ebadf0c 100644 --- a/src/main/java/me/zhyd/oauth/model/AuthToken.java +++ b/src/main/java/me/zhyd/oauth/model/AuthToken.java @@ -17,4 +17,12 @@ public class AuthToken { private String uid; private String openId; private String accessCode; + + /** + * Google附带属性 + */ + private String scope; + private String tokenType; + private String idToken; + } diff --git a/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java b/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java new file mode 100644 index 0000000..52b2bd8 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthGoogleRequest.java @@ -0,0 +1,63 @@ +package me.zhyd.oauth.request; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONObject; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthSource; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.utils.UrlBuilder; + +/** + * Google登录 + * + * @author yangkai.shen (https://xkcoding.com) + * @version 1.3 + * @since 1.3 + */ +public class AuthGoogleRequest extends BaseAuthRequest { + + public AuthGoogleRequest(AuthConfig config) { + super(config, AuthSource.GOOGLE); + } + + @Override + protected AuthToken getAccessToken(String code) { + String accessTokenUrl = UrlBuilder.getGoogleAccessTokenUrl(config.getClientId(), config.getClientSecret(), code, config + .getRedirectUri()); + HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); + JSONObject object = JSONObject.parseObject(response.body()); + + if (object.containsKey("error") || object.containsKey("error_description")) { + throw new AuthException("get google access_token has error:[" + object.getString("error") + "], error_description:[" + object + .getString("error_description") + "]"); + } + + return AuthToken.builder() + .accessToken(object.getString("access_token")) + .expireIn(object.getIntValue("expires_in")) + .scope(object.getString("scope")) + .tokenType(object.getString("token_type")) + .idToken(object.getString("id_token")) + .build(); + } + + @Override + protected AuthUser getUserInfo(AuthToken authToken) { + String accessToken = authToken.getIdToken(); + HttpResponse response = HttpRequest.get(UrlBuilder.getGoogleUserInfoUrl(accessToken)).execute(); + String userInfo = response.body(); + JSONObject object = JSONObject.parseObject(userInfo); + return AuthUser.builder() + .username(object.getString("name")) + .avatar(object.getString("picture")) + .nickname(object.getString("name")) + .location(object.getString("locale")) + .email(object.getString("email")) + .token(authToken) + .source(AuthSource.GOOGLE) + .build(); + } +} diff --git a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java index 1e0feab..5467739 100644 --- a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java +++ b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java @@ -17,6 +17,10 @@ public class UrlBuilder { private static final String GITHUB_USER_INFO_PATTERN = "{0}?access_token={1}"; private static final String GITHUB_AUTHORIZE_PATTERN = "{0}?client_id={1}&state=1&redirect_uri={2}"; + private static final String GOOGLE_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&scope=openid%20email%20profile&redirect_uri={2}&state={3}"; + private static final String GOOGLE_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&code={3}&redirect_uri={4}&grant_type=authorization_code"; + private static final String GOOGLE_USER_INFO_PATTERN = "{0}?id_token={1}"; + private static final String WEIBO_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; private static final String WEIBO_USER_INFO_PATTERN = "{0}?{1}"; private static final String WEIBO_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}"; @@ -492,4 +496,38 @@ public class UrlBuilder { public static String getTaobaoAuthorizeUrl(String clientId, String redirectUrl) { return MessageFormat.format(TAOBAO_AUTHORIZE_PATTERN, ApiUrl.TAOBAO.authorize(), clientId, redirectUrl); } + + /** + * 获取Google授权地址 + * + * @param clientId google 应用的Client ID + * @param redirectUrl google 应用授权成功后的回调地址 + * @return full url + */ + public static String getGoogleAuthorizeUrl(String clientId, String redirectUrl) { + return MessageFormat.format(GOOGLE_AUTHORIZE_PATTERN, ApiUrl.GOOGLE.authorize(), clientId, redirectUrl, System.currentTimeMillis()); + } + + /** + * 获取Google token的接口地址 + * + * @param clientId google应用的Client ID + * @param clientSecret google应用的Client Secret + * @param code google授权前的code,用来换token + * @param redirectUri 待跳转的页面 + * @return full url + */ + public static String getGoogleAccessTokenUrl(String clientId, String clientSecret, String code, String redirectUri) { + return MessageFormat.format(GOOGLE_ACCESS_TOKEN_PATTERN, ApiUrl.GOOGLE.accessToken(), clientId, clientSecret, code, redirectUri); + } + + /** + * 获取Google用户详情的接口地址 + * + * @param token google 应用的token + * @return full url + */ + public static String getGoogleUserInfoUrl(String token) { + return MessageFormat.format(GOOGLE_USER_INFO_PATTERN, ApiUrl.GOOGLE.userInfo(), token); + } } diff --git a/src/test/java/me/zhyd/oauth/AuthRequestTest.java b/src/test/java/me/zhyd/oauth/AuthRequestTest.java index 8e32bf7..de29fbd 100644 --- a/src/test/java/me/zhyd/oauth/AuthRequestTest.java +++ b/src/test/java/me/zhyd/oauth/AuthRequestTest.java @@ -141,4 +141,17 @@ public class AuthRequestTest { // 授权登录后会返回一个code,用这个code进行登录 AuthResponse login = authRequest.login("code"); } + + @Test + public void googleTest() { + AuthRequest authRequest = new AuthGoogleRequest(AuthConfig.builder() + .clientId("clientId") + .clientSecret("clientSecret") + .redirectUri("redirectUri") + .build()); + // 返回授权页面,可自行调整 + String url = authRequest.authorize(); + // 授权登录后会返回一个code,用这个code进行登录 + AuthResponse login = authRequest.login("code"); + } } -- GitLab