You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android端OAuth2对接Spring Boot服务端实现Token认证

我刚好做过类似的Spring Boot + Android Google OAuth2登录的场景,你的核心问题其实是完成「Android拿到Google IdToken后,和自有服务端完成身份校验并获取自有AccessToken」这一环,下面给你一步步拆解可运行的方案:

1. Android端:将Google IdToken发送到自有Spring Boot服务端

你已经能获取到Google的IdToken了,接下来需要把这个Token通过POST请求传给你的服务端接口。这里用Retrofit举例(OkHttp写法逻辑一致):

第一步:定义API接口与数据模型

// 替换为你的服务端基础地址
interface AuthApi {
    @POST("auth/google-login")
    suspend fun loginWithGoogle(@Body request: GoogleLoginRequest): Response<AuthResponse>
}

// 传给服务端的请求体
data class GoogleLoginRequest(
    val idToken: String
)

// 服务端返回的响应模型(和React端拿到的结构保持一致)
data class AuthResponse(
    val accessToken: String,
    val tokenType: String = "Bearer"
)

第二步:在Google登录回调中发送请求

// 假设你已经通过Google Sign-In API拿到了idToken
val idToken = account.idToken ?: return

// 初始化Retrofit实例
val authApi = Retrofit.Builder()
    .baseUrl("https://your-domain.com/api/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()
    .create(AuthApi::class.java)

// 协程中发送请求(避免阻塞主线程)
CoroutineScope(Dispatchers.IO).launch {
    try {
        val response = authApi.loginWithGoogle(GoogleLoginRequest(idToken))
        if (response.isSuccessful) {
            val authResponse = response.body() ?: return@launch
            // 将AccessToken保存到本地(建议用EncryptedSharedPreferences加密存储)
            saveAccessToken(authResponse.accessToken)
            // 登录成功,跳转到主页面
        } else {
            // 处理登录失败,比如提示用户"登录验证失败"
        }
    } catch (e: Exception) {
        // 处理网络异常,比如无网络、连接超时等
    }
}

2. Spring Boot端:接收IdToken并完成身份校验 + 生成自有AccessToken

这一步是核心,你需要写一个自定义登录接口,验证Google IdToken的合法性,再生成和React端一致的AccessToken:

第一步:添加Google IdToken验证依赖

如果还没添加,在pom.xml(Maven)中引入:

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.34.1</version>
</dependency>

第二步:编写登录控制器

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    private final GoogleIdTokenVerifier verifier;
    private final JwtTokenProvider jwtTokenProvider;
    private final UserRepository userRepository;

    // 构造注入:配置Android应用的Google客户端ID(从Google Cloud Console获取)
    public AuthController(@Value("${google.android.client-id}") String androidClientId,
                          JwtTokenProvider jwtTokenProvider,
                          UserRepository userRepository) {
        GoogleIdTokenVerifier.Builder builder = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance())
                .setAudience(Collections.singletonList(androidClientId));
        this.verifier = builder.build();
        this.jwtTokenProvider = jwtTokenProvider;
        this.userRepository = userRepository;
    }

    @PostMapping("/google-login")
    public ResponseEntity<AuthResponse> loginWithGoogle(@RequestBody GoogleLoginRequest request) {
        try {
            // 验证Google IdToken的合法性(自动校验签名、受众、过期时间等)
            GoogleIdToken idToken = verifier.verify(request.getIdToken());
            if (idToken == null) {
                return ResponseEntity.badRequest().body(new AuthResponse(null, "无效的IdToken"));
            }

            // 提取Google用户信息
            GoogleIdToken.Payload payload = idToken.getPayload();
            String googleId = payload.getSubject();
            String email = payload.getEmail();
            String name = (String) payload.get("name");
            String pictureUrl = (String) payload.get("picture");

            // 查找或创建本地用户(和React端登录时的逻辑完全一致)
            User user = userRepository.findByGoogleId(googleId)
                    .orElseGet(() -> {
                        User newUser = new User();
                        newUser.setGoogleId(googleId);
                        newUser.setEmail(email);
                        newUser.setName(name);
                        newUser.setAvatarUrl(pictureUrl);
                        return userRepository.save(newUser);
                    });

            // 生成自有服务的AccessToken(复用React端的JWT生成逻辑)
            String accessToken = jwtTokenProvider.generateToken(user);

            return ResponseEntity.ok(new AuthResponse(accessToken, "Bearer"));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(new AuthResponse(null, "IdToken验证失败:" + e.getMessage()));
        }
    }

    // 内部DTO类
    public static class GoogleLoginRequest {
        private String idToken;
        public String getIdToken() { return idToken; }
        public void setIdToken(String idToken) { this.idToken = idToken; }
    }

    public static class AuthResponse {
        private String accessToken;
        private String tokenType;
        public AuthResponse(String accessToken, String tokenType) {
            this.accessToken = accessToken;
            this.tokenType = tokenType;
        }
        public String getAccessToken() { return accessToken; }
        public String getTokenType() { return tokenType; }
    }
}

第三步:确保JWT生成逻辑和React端一致

这里的JwtTokenProvider必须是你已经在React端登录流程中使用的类,保证签名密钥、过期时间、Claim字段等完全一致,这样服务端才能正常识别Android端携带的Token。

3. Android端:在后续请求中携带AccessToken

每次发送API请求时,自动在请求头中添加Authorization: Bearer <你的AccessToken>,还是用Retrofit举例:

// 创建带拦截器的OkHttpClient
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor { chain ->
        val originalRequest = chain.request()
        // 从本地获取保存的AccessToken
        val accessToken = getSavedAccessToken()
        // 构建带Authorization头的新请求
        val newRequest = originalRequest.newBuilder()
            .header("Authorization", "Bearer $accessToken")
            .build()
        chain.proceed(newRequest)
    }
    .build()

// 初始化业务API服务
val apiService = Retrofit.Builder()
    .baseUrl("https://your-domain.com/api/")
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .build()
    .create(YourBusinessApi::class.java)

重要注意事项

  • 确保Google Cloud Console中,你的Android应用客户端ID已添加到OAuth 2.0授权列表,服务端配置的google.android.client-id必须和这个ID完全一致。
  • Android端存储AccessToken时,建议用EncryptedSharedPreferences或Jetpack Security加密,避免明文泄露。
  • 测试时可以先通过Postman模拟发送IdToken请求,确认服务端接口正常返回AccessToken后,再在Android端调试。

内容的提问来源于stack exchange,提问作者Fily1212

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:15:26