在当今的互联网应用中,单点登录(SSO)已成为提升用户体验的重要功能 —— 用户无需重复注册账号,通过常用的第三方平台(如 Google、GitHub)即可快速登录。本文将详细介绍如何基于 OAuth 2.0 协议,使用 Java 结合 JustAuth 框架实现 Google 账号单点登录,涵盖从 Google 平台配置到前后端代码落地的完整流程。
一、前置知识:Google 账号登录核心原理
Google 账号登录基于 OAuth 2.0 授权协议,核心流程可概括为 3 步:
- 应用引导用户跳转至 Google 授权页面,用户完成身份验证并同意授权;
- Google 授权服务器向应用的回调地址返回授权码;
- 应用通过授权码向 Google 申请访问令牌,进而获取用户基本信息,最终完成登录逻辑。
本文将使用 JustAuth 框架(轻量级 OAuth 工具包)简化开发,避免重复编写 OAuth 协议相关的底层代码。
二、前期准备:Google Cloud 平台服务配置
要实现 Google 登录,首先需要在 Google Cloud 平台创建应用并配置授权信息,这是整个流程的基础。
1. 登录 Google Cloud 平台
访问 Google Cloud 控制台,使用 Google 账号登录。
2. 创建 / 选择项目
- 若已有项目:直接在顶部项目列表中选择目标项目;
- 若新建项目:点击顶部「项目」→「新建项目」,输入项目名称(如「Java-Google-SSO-Demo」),完成创建后等待项目初始化(约 1-2 分钟)。

3. 配置「OAuth 同意屏幕」
新创建的项目必须先配置「同意屏幕」,否则无法创建客户端凭证。

- 在左侧菜单找到「API 和服务」→「OAuth 同意屏幕」;
选择「外部」(适用于面向公众的应用,内部应用仅适用于企业域内用户),点击「创建」;

- 填写「应用信息」:
- 应用名称:将显示在 Google 登录授权页面(如「我的 Java 应用」);
- 支持邮箱:用于接收 Google 相关通知;
- 后续步骤(范围、测试用户、摘要)保持默认配置,点击「提交」即可(测试阶段无需审核,直接可用)。
4. 创建 Client 客户端(关键!)
客户端凭证(Client ID、Client Secret)是应用与 Google 授权服务器通信的身份标识,需重点配置。
在左侧菜单找到「API 和服务」→「凭据」→「创建凭据」→「OAuth 客户端 ID」;

应用类型选择「Web 应用」,填写名称(如「Java-Web-SSO」);

- 配置回调地址(Redirect URI):
- 这是 Google 授权成功后跳转的地址,必须与后端代码中配置的一致(如 http://localhost:8080/google-login-callback);
本地测试可添加 http://localhost:8080/*,线上环境需填写真实域名;

- 点击「创建」,记录生成的 Client ID 和 Client Secret(后续代码会用到,切勿泄露)。
三、前端实现:Google 登录按钮与跳转
前端只需提供一个登录按钮,点击后跳转至后端接口,由后端引导至 Google 授权页面(避免前端直接与 Google 交互,保证安全性)。
本文以 Vue 为例,其他框架(React、Angular)逻辑一致:
<template>
<!-- 页面中的 Google 登录按钮 -->
<button
class="google-login-btn"
@click="handleGoogleLogin"
>
<i class="icon-google"></i> 用 Google 账号登录
</button>
</template>
<script>
export default {
name: 'LoginPage',
methods: {
/**
* 处理 Google 登录点击事件
* 核心:跳转至后端接口,由后端重定向到 Google 授权页
*/
handleGoogleLogin() {
// 后端接口地址(需与后端服务端口一致,如本地 8080 端口)
window.location.href = "http://localhost:8080/google-login";
}
}
};
</script>
<style scoped>
.google-login-btn {
padding: 8px 16px;
background: #4285F4;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>注意:此处需使用 window.location.href 进行页面级跳转,而非异步请求(axios/fetch)—— 因为 Google 授权页面需要用户手动交互(输入账号密码、同意授权)。
四、后端实现:基于 JustAuth 框架的核心逻辑
后端使用 Spring Boot + JustAuth 框架,主要实现两个接口:
- google-login:引导用户跳转至 Google 授权页;
- google-login-callback:接收 Google 回调,处理授权逻辑并完成登录。
1. 第一步:添加 JustAuth 依赖
在 pom.xml 中引入 JustAuth 最新版本(版本可从 JustAuth GitHub 发布页 获取):
<!-- JustAuth:轻量级 OAuth 工具包,简化第三方登录开发 -->
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
<version>1.16.5</version> <!-- 替换为最新版本 -->
</dependency>
<!-- 若使用 Spring Boot,需确保已引入 web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>2. 第二步:实现「引导授权」接口(/google-login)
该接口的作用是:接收前端登录请求,生成 Google 授权地址,并将页面重定向至该地址。
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.request.AuthGoogleRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
@RestController
@AllArgsConstructor
public class AuthController {
/**
* Google 登录引导:重定向至 Google 授权页
* @param response 用于重定向的响应对象
* @throws IOException 重定向异常
*/
@GetMapping("/google-login")
public void googleLogin(HttpServletResponse response) throws IOException {
// 1. 创建 Google 授权请求对象
AuthRequest authRequest = getAuthRequest();
// 2. 生成授权地址(包含随机 State,防止 CSRF 攻击)
String googleAuthUrl = authRequest.authorize(AuthStateUtils.createState());
// 3. 重定向至 Google 授权页
response.sendRedirect(googleAuthUrl);
}
/**
* 封装 Google 授权配置(抽离为工具方法,便于复用)
* @return AuthRequest 授权请求对象
*/
private AuthRequest getAuthRequest() {
return new AuthGoogleRequest(AuthConfig.builder()
// 1. 填入 Google Cloud 配置的 Client ID
.clientId("你的 Client ID")
// 2. 填入 Google Cloud 配置的 Client Secret
.clientSecret("你的 Client Secret")
// 3. 填入 Google Cloud 配置的回调地址(必须一致!)
.redirectUri("http://localhost:8080/google-login-callback")
// 4. (可选)国内环境配置代理(Google 服务需科学上网)
.httpConfig(HttpConfig.builder()
.timeout(15000) // 超时时间:15秒
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7897))) // 本地代理地址
.build())
.build());
}
}关键说明:
- AuthStateUtils.createState():生成随机 State 参数,用于防止跨站请求伪造(CSRF)攻击,Google 会在回调时带回该参数,JustAuth 会自动校验;
- 代理配置:国内环境访问 Google 服务需配置代理(如 Clash、V2Ray),需将 host 和 port 替换为本地代理的实际参数;
- Client ID/Secret/Redirect URI:必须与 Google Cloud 配置完全一致,否则会报「无效客户端」或「回调地址不匹配」错误。
3. 第三步:实现「回调处理」接口(/google-login-callback)
用户在 Google 授权页完成操作后,Google 会将页面重定向至我们配置的回调地址,并携带 授权码(code)和 State 参数。该接口需完成以下逻辑:
- 接收 Google 回调参数;
- 通过 JustAuth 解析授权码,获取用户信息;
- 结合业务逻辑完成登录(如创建用户、生成自定义 Token);
- 重定向至前端首页(携带自定义 Token)。
import me.zhyd.oauth.model.AuthResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
public class AuthController {
// 从配置文件读取前端首页地址(如:http://localhost:8081/home?token=)
@Value("${login.redirect.page}")
private String loginRedirectPage;
// 注入业务层服务(处理用户登录逻辑)
private final AuthService authService;
public AuthController(AuthService authService) {
this.authService = authService;
}
/**
* Google 登录回调:处理授权逻辑,完成登录
* @param callback Google 回调参数(包含 code、state 等)
* @param response 用于重定向至前端首页
* @throws IOException 重定向异常
*/
@GetMapping("/google-login-callback")
public void googleLoginCallback(AuthCallback callback, HttpServletResponse response) throws IOException {
// 1. 创建授权请求对象(复用之前的配置)
AuthRequest authRequest = getAuthRequest();
// 2. 解析回调参数,获取 Google 用户信息(JustAuth 自动处理 code 换 token、拉取用户信息)
AuthResponse authResponse = authRequest.login(callback);
// 3. 业务层处理:结合 Google 用户信息完成登录(核心逻辑)
// 自定义 VO:包含系统生成的 Token、用户信息等
AuthLoginRespVO loginResult = authService.doGoogleLogin(authResponse);
// 4. 重定向至前端首页,并携带系统 Token(前端通过 Token 验证登录状态)
response.sendRedirect(loginRedirectPage + loginResult.getAccessToken());
}
// (省略 getAuthRequest() 方法,与上文一致)
}4. 补充:业务层登录逻辑(AuthService)
doGoogleLogin 方法是业务核心,需根据项目需求实现(如「用户首次登录自动创建账号」「已存在用户直接关联登录」)。以下是一个简化示例:
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
/**
* Google 登录业务逻辑
* @param authResponse JustAuth 返回的 Google 用户信息
* @return AuthLoginRespVO 系统登录结果(含 Token)
*/
public AuthLoginRespVO doGoogleLogin(AuthResponse authResponse) {
// 1. 解析 Google 用户信息(AuthUser 包含用户名、邮箱、头像等)
AuthUser googleUser = (AuthUser) authResponse.getData();
String googleOpenId = googleUser.getUuid(); // Google 用户唯一标识(OpenID)
String googleEmail = googleUser.getEmail(); // Google 邮箱(需用户授权才能获取)
// 2. 数据库查询:判断用户是否已关联 Google 账号
User existingUser = userMapper.selectByGoogleOpenId(googleOpenId);
User loginUser;
if (existingUser != null) {
// 3. 已关联用户:直接更新登录时间等信息
existingUser.setLastLoginTime(new Date());
userMapper.updateById(existingUser);
loginUser = existingUser;
} else {
// 4. 未关联用户:创建新用户(或引导绑定已有账号)
loginUser = new User();
loginUser.setGoogleOpenId(googleOpenId);
loginUser.setUsername(googleUser.getNickname());
loginUser.setEmail(googleEmail);
loginUser.setAvatar(googleUser.getAvatar());
loginUser.setCreateTime(new Date());
userMapper.insert(loginUser);
}
// 5. 生成系统自定义 Token(如 JWT Token)
String systemToken = jwtUtils.generateToken(loginUser.getId());
// 6. 返回登录结果(Token + 用户基本信息)
return new AuthLoginRespVO()
.setAccessToken(systemToken)
.setUsername(loginUser.getUsername())
.setAvatar(loginUser.getAvatar());
}
}五、整体流程回顾
- 用户点击前端「Google 登录」按钮,跳转至后端 /google-login 接口;
- 后端生成 Google 授权地址,重定向至 Google 授权页;
- 用户在 Google 页输入账号密码,同意授权后,Google 重定向至后端 /google-login-callback 接口,并携带 code;
- 后端通过 code 向 Google 申请 Token,拉取用户信息;
- 后端结合用户信息完成登录逻辑,生成系统 Token;
- 后端重定向至前端首页,携带 Token;
- 前端解析 Token,验证登录状态,跳转至首页。
六、常见问题与注意事项
- 回调地址不匹配:检查 Google Cloud 配置的 Redirect URI 与后端 redirectUri 是否完全一致(包括协议、域名、端口);
- 国内环境无法访问 Google:需配置代理(如上文的 httpConfig),确保后端服务能正常调用 Google 授权接口;
- 用户信息无法获取:需在 Google Cloud「OAuth 同意屏幕」中添加「邮箱」「个人资料」等权限范围;
- State 验证失败:JustAuth 会自动校验 State,若报错需检查是否在授权过程中修改了 State 参数;
- Client Secret 泄露风险:Client Secret 需存储在后端配置文件(如 application.yml),切勿暴露在前端代码中。
七、总结
本文基于 OAuth 2.0 协议和 JustAuth 框架,实现了 Google 账号单点登录的完整流程,核心在于「Google 平台配置」「授权引导」「回调处理」三个环节。JustAuth 框架极大简化了 OAuth 协议的底层实现,让开发者可以专注于业务逻辑(如用户关联、Token 生成)。
实际项目中,还可根据需求扩展功能,如「账号绑定」「登录日志记录」「Token 过期刷新」等。希望本文能为你的第三方登录开发提供参考!
评论 (0)