Google登录授权详细过程
这篇文章包含了google登录授权从API创建、到使用Java代码完成登录的一个完整demo。目录了解Auth2.0创建API服务使用API了解Auth2.0google相关文档:https://developers.google.com/identity/protocols/oauth2google账号授权登录用的就是Auth2.0协议。举一个例子了解Auth2.0的设计模式。令牌 Token你
前言
这篇文章包含了google登录授权从API创建、到使用Java代码完成登录的一个完整demo。
主要为了实现google关联用户的服务,如google merchant center等。
如果仅仅需要使用google邮箱登录,建议由前端实现google登录:
1,国内网络和google服务是不通的,国内服务器需要解决网络问题,如果由前端实现google登录用户解决网络问题即可;
2,前端实现更简单
目录
了解Auth2.0
google相关文档:https://developers.google.com/identity/protocols/oauth2
google账号授权登录用的就是Auth2.0协议。
举一个例子了解Auth2.0的设计模式。
- 令牌 Token
你在公司某个周五的下午点了一杯奶茶,楼下有个需要密码才能进来的门禁,你当然不会把密码告诉配送小哥,你告诉配送小哥在门禁App登记一下访客登记卡,你同意一系列访客管理须知后,发短信验证码给他,小哥输入验证码并获得访客卡顺利进来了;
- 授权域 Scopes
配送小哥进来后拿这访卡刷电梯,有两个电梯都能上去你所在的楼层,电梯A能到达公司的办公场所,电梯B能到达用餐室,但小哥只能使用电梯B,因为你在用餐室等着了,没必要去到办公室打扰到其他同事;
- 令牌过期
周六的时候你又在公司同一家店点了一杯奶茶,奶茶送到时发现发现之前申请的访客卡是临时的,要重新登记,只是你发送验证码的时候不再需要经过一系列访客管理须知,因为门禁app上已经有你对配送小哥的授权记录了;
- 离线令牌 Refresh Token
点了两次的你觉得这家店奶茶很好喝,于是你在这家店开了会员。但有时你在开会无法及时给配送小哥访客卡验证码,于是你让店家登记一个会员卡,凭这个会员卡可以直接要到访客卡,无需授权;
- 撤销令牌
有一天你在网上冲浪看到拓海的近照,你决定戒奶,于是在门禁app上把店家的访客卡和会员卡给取消了。
创建API服务
了解完auth2.0之后,开始正式使用google的授权登录。
现在演示的是一个测试项目,google对测试项目没有强校验,所以下面信息填写可以随意。确认可行性后创建生产项目时需要进行认证。
之外,你可能需要在YouTube上传一个使用录屏视频给审核员,来演示你是利用谷歌api来完成哪一些事情的,演示视频项目内容需要为英文,如果你的项目不是英文可以在演示的时候翻译成英文
用谷歌账号注册API
用谷歌账号登录后创建一个【test】项目
创建完项目【test】,来到控制台
题外话:如果你想使用google某些功能,可以到Api库添加Api;例如谷歌翻译,搜索并启用。(ps:google翻译api是收费的,需要一个结算管理账号)
配置同意屏
同意屏幕:用户在你的应用登录时,google展示给用户的信息,包括网站域名与logo、隐私政策
应用网域
包含四部分信息,网站域名、网站首页、隐私政策和服务条款。
范围
即授权域。这也是会在用户同意屏幕展示的。
我们需要保存邮箱账号,所以只使用/auth/userinfo/email这个授权范围
创建凭据
选择OAuth客户端ID
选择web应用,并配置授权登录后的url(url需要是https协议,尽管只是个测试项目)
创建后就获得客户端id和秘钥
使用API服务
引入maven
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>0.22.2</version>
</dependency>
配置类
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.zz.saas.shoplus.portal.bean.GoogleAuthorization;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* google登录授权配置
*/
@Configuration
@Slf4j
public class GoogleAuthorizationConfig {
private static final String clientId = "your client id";
private static final String clientSecret = "your client secret";
private static final String applicationName = "your application name";
private static final String redirectUrl = "https://test.com/google-login";
@Bean(name = "googleAuthorization")
public GoogleAuthorization googleFeed() {
GoogleClientSecrets clientSecrets = null;
try {
GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
details.setClientId(clientId);
details.setClientSecret(clientSecret);
clientSecrets = new GoogleClientSecrets();
clientSecrets.setInstalled(details);
} catch (Exception e) {
log.error("authorization configuration error:{}", e.getMessage());
}
// 构建bean
return GoogleAuthorization.builder()
.googleClientSecrets(clientSecrets)
.applicationName(applicationName)
.redirectUrl(redirectUrl)
.build();
}
}
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
/**
* google授权
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class GoogleAuthorization {
// 应用名
private String applicationName;
// 重定向路径
private String redirectUrl;
// 应用凭证
private GoogleClientSecrets googleClientSecrets;
// 授权域
private final static List<String> scopes = Collections.singletonList(
"https://www.googleapis.com/auth/userinfo.email"
);
public List<String> getScopes(){
return scopes;
}
}
获得发起登录请求链接
// 导包信息
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.*;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
@Autowired
private GoogleAuthorizationService googleAuthorizationService;
public String authorizingUrl() throws GeneralSecurityException, IOException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
// 创建验证流程对象
GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow
.Builder(httpTransport, jsonFactory, googleAuthorization.getGoogleClientSecrets(), googleAuthorization.getScopes())
// AccessType为离线offline,才能获得Refresh Token
.setAccessType("offline").build();
if (googleAuthorizationCodeFlow != null) {
// 返回跳转登录请求
return googleAuthorizationCodeFlow.newAuthorizationUrl().setRedirectUri(googleAuthorization.getRedirectUrl()).build();
}
return null;
}
调用方法authorizingUrl,得到一个跳转的url:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=YourClientId&redirect_uri=https://test.com/google-login&response_type=code&scope=https://www.googleapis.com/auth/userinfo.email
放到postman看看参数
在浏览器访问这个url,跳转到同意屏幕,可以看到之前创建api的应用信息
登录一个谷歌账号,授权之后462,因为域名是随便填的,但是主要是获得重定向后的URL
重定向URL填充了一个授权码code,接下来就可以拿这个授权码去授权了
使用授权码授权
用授权码获得登录token
// 导包信息
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.*;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
public void authorizing(String authorizationCode) throws GeneralSecurityException, IOException {
// 创建请求凭证
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow
.Builder(httpTransport, jsonFactory, googleAuthorization.getGoogleClientSecrets(), googleAuthorization.getScopes())
// AccessType为离线offline,才能获得Refresh Token
.setAccessType("offline").build();
GoogleAuthorizationCodeTokenRequest tokenRequest = googleAuthorizationCodeFlow.newTokenRequest(authorizationCode);
tokenRequest.setRedirectUri(googleAuthorization.getRedirectUrl());
// 发起授权请求,获得Token和Refresh Token
GoogleTokenResponse tokenResponse = tokenRequest.execute();
String token = tokenResponse.getAccessToken();
String refreshToken = tokenResponse.getRefreshToken();
// 获得email
String email = null;
if (StringUtils.isNotBlank(tokenResponse.getIdToken())) {
GoogleIdTokenVerifier idTokenVerifier = new GoogleIdTokenVerifier.Builder(googleAuthorizationCodeFlow.getTransport(), googleAuthorizationCodeFlow.getJsonFactory()).build();
idTokenVerifier.verify(tokenResponse.getIdToken());
GoogleIdToken googleIdToken = idTokenVerifier.verify(tokenResponse.getIdToken());
if (googleIdToken != null && googleIdToken.getPayload() != null) {
email = googleIdToken.getPayload().getEmail();
}
}
// todo 保留账号token、refreshToken、email信息
}
Refresh Token
token的有效期为1小时,token过期之后让用户跳转到登录页重新登录就可以了;
但如果需要离线使用谷歌api时,就可以使用Refresh Token
public String refreshToken(String refreshToken) throws IOException {
String token = null;
// 创建刷新请求对象
GoogleRefreshTokenRequest googleRefreshTokenRequest = new GoogleRefreshTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
refreshToken,
googleAuthorization.getGoogleClientSecrets().getDetails().getClientId(),
googleAuthorization.getGoogleClientSecrets().getDetails().getClientSecret());
// 发起刷新请求
GoogleTokenResponse googleTokenResponse = googleRefreshTokenRequest.execute();
if (googleTokenResponse != null && StringUtils.isNotBlank(googleTokenResponse.getAccessToken())) {
token = googleTokenResponse.getAccessToken();
}
return null;
}
更多推荐
所有评论(0)