google-idtoken验证
This commit is contained in:
@@ -1,24 +1,19 @@
|
||||
package com.accompany.admin.controller.api;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.accompany.admin.service.api.MyApiService;
|
||||
import com.accompany.business.message.UserEventBeginEndMessage;
|
||||
import com.accompany.business.service.activity.h5.ActivityUserLevelExpService;
|
||||
import com.accompany.business.service.mq.RocketMQService;
|
||||
import com.accompany.business.service.room.RoomService;
|
||||
import com.accompany.business.vo.RoomVo;
|
||||
import com.accompany.common.netease.ErBanNetEaseService;
|
||||
import com.accompany.common.netease.neteaseacc.result.RoomMemberRet;
|
||||
import com.accompany.common.result.BusiResult;
|
||||
import com.accompany.common.status.BusiStatus;
|
||||
import com.accompany.common.utils.DateTimeUtil;
|
||||
import com.accompany.core.exception.AdminServiceException;
|
||||
import com.accompany.core.exception.ServiceException;
|
||||
import com.accompany.core.service.GoogleTokenVerifier;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@@ -313,4 +308,16 @@ public class MyApiController {
|
||||
return BusiResult.success();
|
||||
}
|
||||
|
||||
|
||||
@Autowired
|
||||
private GoogleTokenVerifier googleTokenVerifier;
|
||||
|
||||
@PostMapping("/auth/google")
|
||||
public GoogleTokenVerifier.GoogleUserInfo authWithGoogle(String idToken) {
|
||||
try {
|
||||
return googleTokenVerifier.verifyAndGetUserInfo(idToken);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Google token verification failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,28 @@
|
||||
<artifactId>accompany-sharding-service</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
<version>2.7.0</version> <!-- 建议使用最新版本 -->
|
||||
</dependency>
|
||||
<!-- gRPC 核心库(提供Context类) -->
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-core</artifactId>
|
||||
<version>1.71.0</version> <!-- 使用最新稳定版 -->
|
||||
</dependency>
|
||||
<!-- OpenCensus(解决trace相关错误) -->
|
||||
<dependency>
|
||||
<groupId>io.opencensus</groupId>
|
||||
<artifactId>opencensus-api</artifactId>
|
||||
<version>0.31.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.opencensus</groupId>
|
||||
<artifactId>opencensus-impl</artifactId>
|
||||
<version>0.31.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,90 @@
|
||||
package com.accompany.core.service;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class GoogleTokenVerifier {
|
||||
|
||||
private final GoogleIdTokenVerifier verifier;
|
||||
private final String clientId;
|
||||
|
||||
public GoogleTokenVerifier(NetHttpTransport transport, GsonFactory jsonFactory, String clientId) {
|
||||
this.clientId = clientId;
|
||||
this.verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
|
||||
.setAudience(Collections.singletonList(clientId))
|
||||
.build();
|
||||
}
|
||||
/**
|
||||
* 验证Token并返回用户信息
|
||||
*/
|
||||
public GoogleUserInfo verifyAndGetUserInfo(String idTokenString) {
|
||||
try {
|
||||
GoogleIdToken idToken = verifier.verify(idTokenString);
|
||||
if (idToken == null) {
|
||||
throw new IllegalArgumentException("Invalid ID token");
|
||||
}
|
||||
|
||||
GoogleIdToken.Payload payload = idToken.getPayload();
|
||||
return new GoogleUserInfo(
|
||||
payload.getSubject(),
|
||||
payload.getEmail(),
|
||||
(String) payload.get("name"),
|
||||
(String) payload.get("picture")
|
||||
);
|
||||
} catch (GeneralSecurityException e) {
|
||||
log.error("verifyAndGetUserInfo:e:{}", e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
log.error("verifyAndGetUserInfo:e:{}", e.getMessage(), e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("verifyAndGetUserInfo:e:{}", e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅获取用户邮箱
|
||||
*/
|
||||
public String getEmailFromToken(String idTokenString) {
|
||||
return verifyAndGetUserInfo(idTokenString).getEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅获取用户ID
|
||||
*/
|
||||
public String getUserIdFromToken(String idTokenString) {
|
||||
return verifyAndGetUserInfo(idTokenString).getUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息DTO
|
||||
*/
|
||||
public static class GoogleUserInfo {
|
||||
private final String userId;
|
||||
private final String email;
|
||||
private final String name;
|
||||
private final String pictureUrl;
|
||||
|
||||
public GoogleUserInfo(String userId, String email, String name, String pictureUrl) {
|
||||
this.userId = userId;
|
||||
this.email = email;
|
||||
this.name = name;
|
||||
this.pictureUrl = pictureUrl;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public String getUserId() { return userId; }
|
||||
public String getEmail() { return email; }
|
||||
public String getName() { return name; }
|
||||
public String getPictureUrl() { return pictureUrl; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package com.accompany.core.service.user;
|
||||
|
||||
import com.accompany.core.service.GoogleTokenVerifier;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
@Data
|
||||
public class GoogleAuthConfig {
|
||||
|
||||
@Value("${google-auth.client-id}")
|
||||
private String clientId;
|
||||
|
||||
|
||||
@Bean
|
||||
public NetHttpTransport netHttpTransport() {
|
||||
return new NetHttpTransport();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GsonFactory gsonFactory() {
|
||||
return new GsonFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GoogleTokenVerifier googleTokenVerifier(NetHttpTransport transport, GsonFactory jsonFactory) {
|
||||
return new GoogleTokenVerifier(transport, jsonFactory, clientId);
|
||||
}
|
||||
|
||||
}
|
@@ -1,11 +1,12 @@
|
||||
package com.accompany.core.service.user.impl;
|
||||
|
||||
import com.accompany.common.utils.GoogleJwtParser;
|
||||
import com.accompany.common.utils.StringUtils;
|
||||
import com.accompany.core.model.GoogleOpenidRef;
|
||||
import com.accompany.core.mybatismapper.GoogleOpenidRefMapper;
|
||||
import com.accompany.core.service.GoogleTokenVerifier;
|
||||
import com.accompany.core.service.user.GoogleOpenidRefService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -21,20 +22,23 @@ import java.util.Optional;
|
||||
public class GoogleOpenidRefServiceImpl extends ServiceImpl<GoogleOpenidRefMapper, GoogleOpenidRef> implements GoogleOpenidRefService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private GoogleTokenVerifier googleTokenVerifier;
|
||||
|
||||
@Override
|
||||
public String getUnionIdByEmail(String email, String idToken) {
|
||||
GoogleOpenidRef googleOpenidRef = baseMapper.selectById(email);
|
||||
return Optional.ofNullable(googleOpenidRef)
|
||||
.map(x -> x.getOpenId())
|
||||
.orElseGet(() -> {
|
||||
String sub = GoogleJwtParser.getSubFromToken(idToken);
|
||||
if (StringUtils.isNotEmpty(sub)) {
|
||||
saveRecord(email, sub);
|
||||
return sub;
|
||||
GoogleTokenVerifier.GoogleUserInfo sub = googleTokenVerifier.verifyAndGetUserInfo(email);
|
||||
if (sub != null && StringUtils.isNotEmpty(sub.getUserId()) && email.equals(sub.getEmail())) {
|
||||
String userId = sub.getUserId();
|
||||
saveRecord(email, userId);
|
||||
return userId;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,23 +1,25 @@
|
||||
package com.accompany.payment.google;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.http.HttpRequestInitializer;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.api.client.util.Preconditions;
|
||||
import com.google.api.client.util.Strings;
|
||||
import com.google.api.services.androidpublisher.AndroidPublisher;
|
||||
import com.google.api.services.androidpublisher.AndroidPublisherScopes;
|
||||
import com.google.auth.http.HttpCredentialsAdapter;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -33,9 +35,6 @@ public class AndroidPublisherHelper {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AndroidPublisherHelper.class);
|
||||
|
||||
/** Global instance of the JSON factory. */
|
||||
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
|
||||
|
||||
/** Global instance of the HTTP transport. */
|
||||
private static HttpTransport HTTP_TRANSPORT;
|
||||
|
||||
@@ -45,6 +44,7 @@ public class AndroidPublisherHelper {
|
||||
private static volatile String oldPackageName;
|
||||
private static volatile String oldCredentialJson;
|
||||
|
||||
private static final GsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
|
||||
|
||||
public static void init(String applicationName, String packageName, String json) throws IOException, GeneralSecurityException {
|
||||
if (needInit(applicationName, packageName, json)) {
|
||||
@@ -56,14 +56,20 @@ public class AndroidPublisherHelper {
|
||||
|
||||
List<String> scopes = new ArrayList<>();
|
||||
scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER);
|
||||
ByteArrayResource resource = new ByteArrayResource(json.getBytes());
|
||||
GoogleCredential credential = GoogleCredential.fromStream(resource.getInputStream())
|
||||
.createScoped(scopes);
|
||||
// 1. 使用HttpCredentialsAdapter包装GoogleCredentials
|
||||
GoogleCredentials credentials = GoogleCredentials.fromStream(
|
||||
new ByteArrayInputStream(json.getBytes()))
|
||||
.createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
|
||||
|
||||
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
|
||||
|
||||
newTrustedTransport();
|
||||
|
||||
//使用谷歌凭据和收据从谷歌获取购买信息
|
||||
androidPublisher = new AndroidPublisher.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
|
||||
// 2. 构建AndroidPublisher实例
|
||||
androidPublisher = new AndroidPublisher.Builder(
|
||||
HTTP_TRANSPORT,
|
||||
JSON_FACTORY,
|
||||
requestInitializer)
|
||||
.setApplicationName(applicationName)
|
||||
.build();
|
||||
|
||||
|
@@ -69,7 +69,7 @@
|
||||
<opencc4j.version>1.7.2</opencc4j.version>
|
||||
<hutool.version>5.8.38</hutool.version>
|
||||
<hippo4j-config-spring-boot-starter.version>1.5.0</hippo4j-config-spring-boot-starter.version>
|
||||
<google-api-services-androidpublisher.version>v3-rev24-1.24.1</google-api-services-androidpublisher.version>
|
||||
<google-api-services-androidpublisher.version>v3-rev20231115-2.0.0</google-api-services-androidpublisher.version>
|
||||
<payermax-server.version>1.0.12</payermax-server.version>
|
||||
<sharding-jdbc.version>5.5.2</sharding-jdbc.version>
|
||||
<commons-lang.version>2.6</commons-lang.version>
|
||||
|
Reference in New Issue
Block a user