原文链接
前言
相对于国内的通讯软件(QQ、微信)的替代主体登录方式所需一系列的资质审查流程,用户使用Google账号进行登录除了需要一些小小技术外,无论对于开发者还是用户都是更方便的。国内这几个东西不是憋着让你手机应用软件验证就是让你用手机收短信,几乎完全把信息安全维护验证工作推给用户,而且对于开发者的限制太多(这一点似乎没有办法,但是本质上也是层层加码的结果)
实现
客户端ID申请
首先我们访问谷歌Oauth2的Web端使用,页面的上方Tab页可以切换不同客户端,这里我们选择Web端。对于该流程不太清楚的小伙伴可以看下左侧前两个Tab,Overview和How user authorization works,我们直接看第三个Get your Google API client ID
点击Configure a project,此时弹出窗口,我们新建一个项目,默认名字My Project,修改项目名称。下一步,定义产品名称,这个就很重要了,因为涉及到后续弹出谷歌登录页面,提示给用户受否授权给XXX,这里XXX就是你的产品名称,所以最好写入一个你希望展示给用户的名称
后续我们选择Web browser,下方填写是通过哪个地址访问的谷歌,以本网站为例即为https://www.astercasc.com,之后由于调试需要,我们还将添加http://localhost:8080。至此创建完成,我们获取了Client ID和Client Secret,可以不用保存,其在控制台随时允许查看。根据下方提示我们进入你的控制台,如有需要,在左上方切换不同的项目
控制台查询和配置
进入指定项目控制台后,在左上点击导航栏标志,呼出隐藏导航栏,选择APIs & Services进入接口服务页面。在左侧导航栏顺序点击OAuth consent screen->Clients,此时位于OAuth 2.0 Client IDs页面,选择刚刚创建的OAuth client即可查看刚刚创建的客户端ID和密钥。这里我们在Authorized JavaScript origins下方添加一行http://localhost:8080用于本机调试,如果小伙伴开的其他端口,相应更改即可
客户端
方案1
不同前端框架,使用接入大同小异,参考Load the client library以及Generate the integration code进行配置即可。这里我们以Vue项目进行演示,方便起见直接引用库vue3-google-login
配置全局客户端ID:
import vue3GoogleLogin from 'vue3-google-login'
// ...
app.use(vue3GoogleLogin, {
clientId: 'your_client_id'
})
app.mount("#app");
代码如下:
<GoogleLogin :callback="googleLoginCallback">
<button class="gsi-material-button">
<div class="gsi-material-button-state"></div>
<div class="gsi-material-button-content-wrapper">
<div class="gsi-material-button-icon">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"
xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;">
<path fill="#EA4335"
d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path>
<path fill="#4285F4"
d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path>
<path fill="#FBBC05"
d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path>
<path fill="#34A853"
d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path>
<path fill="none" d="M0 0h48v48H0z"></path>
</svg> </div> </div> </button></GoogleLogin>
.gsi-material-button {
background-color: transparent;
background-image: none;
border: none;
-webkit-border-radius: 20px;
border-radius: 20px;
box-sizing: border-box;
color: #1f1f1f;
cursor: pointer;
font-family: 'Roboto', arial, sans-serif;
font-size: 14px;
letter-spacing: 0.25px;
outline: none;
overflow: hidden;
padding: 0;
position: relative;
text-align: center;
-webkit-transition: background-color .218s, border-color .218s, box-shadow .218s;
transition: background-color .218s, border-color .218s, box-shadow .218s;
vertical-align: middle;
white-space: nowrap;
max-width: 400px;
min-width: min-content;
height: 2rem;
width: 2rem;
}
根据你的配置不同,点击之后出现跳转/窗口,并正常展示你所配置的产品文本,基本上前端和谷歌的交互就完成了,回调函数示例如下:
const googleLoginCallback = (response) => {
if (!response || !response.code) {
notifyTopWarning(t('main_login_google_client_fail'));
return
}
userLoginGoogle({code: response.code}).then(res => {
if (!res || !res.data || !res.data.data) {
return
}
globalState.updateUserData(res.data.data)
notifyTopPositive(t('main_login_success'))
})
}
方案2
这里我们自己构造Google OAuth 2.0 URL,而不是依赖https://accounts.google.com/gsi/client。上一种方法虽然没有显示依赖该脚本,但是本质上还是利用官网的客户端库,官方的库更多的是服务于当前窗口,如果我们使用直接跳转到谷歌页面,然后由谷歌回调的话,可以最大程度精简自己的程序
我们这里既然需要谷歌回调我们,就需要在前文提到的OAuth 2.0 Client IDs页面中配置重定向链接,比如添加URI为https://www.astercasc.com/auth/google/callback,注意这里一定要和后面的redirect_uri参数严格相同,一模一样,基本构造如下:
https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID&redirect_uri=https://www.astercasc.com/auth/google/callback&response_type=code&scope=email profile&access_type=offline
更多参数参考OAuth 2.0 for Client-side Web Applications
当用用户登录完成后,谷歌就会携带code回调我们页面,此时在该页面上完成上述googleLoginCallback函数内容即可。即,将code传入服务端验证,获取用户信息,返回正常登录token完成登录
服务端
我们依旧使用Spring Boot作为服务端,正常模板代码就不展示了,只展示和谷歌互动的部分。将谷歌返回的code传入服务端,我们现在需要用这个code向谷歌请求用户数据,并且解析。这样我们就获得了邮箱,那么将该邮箱走正常注册/登录步骤返回token即可:
@Data
public class UserGoogleDto {
private String email;
private String name;
private String picture;
private String given_name;
private String family_name;
}
private GoogleTokenResponse exchangeCodeForToken(String code) {
try {
Proxy proxy;
if (CaskBaseConstant.TEST_ENV.equals(active)) {
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort));
} else {
proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyAddress, proxyPort));
}
NetHttpTransport transport = new NetHttpTransport.Builder().setProxy(proxy).build();
return new GoogleAuthorizationCodeTokenRequest(
transport,
GsonFactory.getDefaultInstance(),
"https://oauth2.googleapis.com/token",
clientId,
secret,
code, redirectUri
).execute();
} catch (IOException ex) {
log.info("[op:exchangeCodeForToken] Get google token from code fail, {}", ex.getMessage());
ex.printStackTrace();
throw new CaskYuiException("谷歌服务器解析错误");
}
}
public UserDto getUserInfo(String authorizationCode) {
try {
GoogleTokenResponse tokenResponse = exchangeCodeForToken(authorizationCode);
GoogleIdToken googleIdToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = googleIdToken.getPayload();
String payloadJson = JSON.toJSONString(payload);
UserGoogleDto UserGoogleData = JSON.parseObject(payloadJson, UserGoogleDto.class);
// Build data
UserDto userData = new UserDto();
userData.setAccount(UserGoogleData.getEmail());
userData.setMail(UserGoogleData.getEmail());
userData.setNickName(UserGoogleData.getName());
userData.setFirstName(UserGoogleData.getFamily_name());
//...
return userData;
} catch (Exception ex) {
log.info("[op:getUserInfo] Parse user data fail, {}", ex.getMessage());
ex.printStackTrace();
throw new CaskYuiException("用户数据解析错误");
}
}
我们这里引用了谷歌的接口开发包,所以比较简单,其他语言的小伙伴可以参考Access Google APIs more easily获取适合的SDK。该代码中没有定义的量都为配置文件参数,比如clientId为谷歌客户端ID,secret为相应密钥,redirectUri为刚才填写的Authorized JavaScript origins链接,注意测试和正式不同,本地测试应当为http://localhost:xxx,如果使用的是第二种方案,则重定向链接为回调的链接,以上文为例,则为https://www.astercasc.com/auth/google/callback,active为当前环境
获得用户数据之后,如果用户邮箱未注册,将用户注册到你的数据库里面,如果已注册,则直接走登录,返回你的登录模块token提供客户端存储即可。至此用户登录完成

1万+

被折叠的 条评论
为什么被折叠?



