google客户端新sdk兼容登录

google客户端新sdk兼容登录
This commit is contained in:
2025-06-20 14:47:24 +08:00
committed by khalil
parent d393ede84d
commit 8a52bffaeb
9 changed files with 233 additions and 9 deletions

View File

@@ -0,0 +1,36 @@
package com.accompany.core.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* google关联表实体类
*
* @author
* @since 2025-06-20
*/
@Data
public class GoogleOpenidRef implements Serializable {
private static final long serialVersionUID = 1L;
/**
* google邮箱
*/
@TableId(value = "email", type = IdType.NONE)
private String email;
/**
* openId
*/
private String openId;
/**
* 创建时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,14 @@
package com.accompany.core.mybatismapper;
import com.accompany.core.model.GoogleOpenidRef;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* google关联表 Mapper 接口
*
* @author
* @since 2025-06-20
*/
public interface GoogleOpenidRefMapper extends BaseMapper<GoogleOpenidRef> {
}

View File

@@ -0,0 +1,17 @@
package com.accompany.core.service.user;
import com.accompany.core.model.GoogleOpenidRef;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* google关联表 服务类
*
* @author
* @since 2025-06-20
*/
public interface GoogleOpenidRefService extends IService<GoogleOpenidRef> {
String getUnionIdByEmail(String email, String idToken);
void saveRecord(String email, String openId);
}

View File

@@ -0,0 +1,49 @@
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.user.GoogleOpenidRefService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Optional;
/**
* google关联表 服务实现类
*
* @author
* @since 2025-06-20
*/
@Service
public class GoogleOpenidRefServiceImpl extends ServiceImpl<GoogleOpenidRefMapper, GoogleOpenidRef> implements GoogleOpenidRefService {
@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)) {
return sub;
}
return null;
});
}
@Override
public void saveRecord(String email, String openId) {
GoogleOpenidRef googleOpenidRef = new GoogleOpenidRef();
googleOpenidRef.setEmail(email);
googleOpenidRef.setOpenId(openId);
googleOpenidRef.setCreateTime(new Date());
baseMapper.insert(googleOpenidRef);
}
}

View File

@@ -0,0 +1,98 @@
package com.accompany.common.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
/**
* Google JWT Token解析工具类
*/
public class GoogleJwtParser {
/**
* 从JWT Token中获取用户唯一标识(sub)
* @param token JWT Token字符串
* @return 用户sub解析失败返回null
*/
public static String getSubFromToken(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getSubject();
} catch (JWTDecodeException e) {
System.err.println("JWT解析失败: " + e.getMessage());
return null;
}
}
/**
* 验证Token是否过期
* @param token JWT Token字符串
* @param leewaySeconds 允许的时间误差(秒)
* @return true=已过期false=未过期解析失败返回true
*/
public static boolean isTokenExpired(String token, int leewaySeconds) {
try {
DecodedJWT jwt = JWT.decode(token);
if (jwt.getExpiresAt() == null) {
return false; // 没有过期时间的token视为永不过期
}
return jwt.getExpiresAt().before(
new Date(System.currentTimeMillis() - leewaySeconds * 1000L));
} catch (JWTDecodeException e) {
System.err.println("JWT解析失败: " + e.getMessage());
return true; // 解析失败视为过期
}
}
/**
* 获取Token中的邮箱地址
* @param token JWT Token字符串
* @return 邮箱地址解析失败返回null
*/
public static String getEmailFromToken(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("email").asString();
} catch (JWTDecodeException e) {
System.err.println("JWT解析失败: " + e.getMessage());
return null;
}
}
/**
* 获取Token中的用户姓名
* @param token JWT Token字符串
* @return 用户姓名解析失败返回null
*/
public static String getNameFromToken(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("name").asString();
} catch (JWTDecodeException e) {
System.err.println("JWT解析失败: " + e.getMessage());
return null;
}
}
public static void main(String[] args) {
String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFiYjc3NGJkODcyOWVhMzhlOWMyZmUwYzY0ZDJjYTk0OGJmNjZmMGYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI1MTUzODE4Nzk2MzUtZHRhc2Y2aDhiYTF1NGlpNTVidW50cmk0bWh2ZzdhZXYuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI1MTUzODE4Nzk2MzUtMnJkam1tYm9nYTUxcnFtMmhhaWFkYWF0bzJlMDg3dXEuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTEzMDk0NTQxMzg0NDU4NzYzMTYiLCJlbWFpbCI6Inpob3V6NDQzNUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6Ilpob3UgWmhvdSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKWFBHcHRFcVpBb1MxSE1RSFFFN3ZWc29hRW9ZOVk2alJ6bHd1a1hSRmh1Mmlfc2c9czk2LWMiLCJnaXZlbl9uYW1lIjoiWmhvdSIsImZhbWlseV9uYW1lIjoiWmhvdSIsImlhdCI6MTc1MDM0MTQ1OSwiZXhwIjoxNzUwMzQ1MDU5fQ.HVdkPFkGN6wdBOorNOqBAMHawXrZrs4hth0cLwuyoqCoyO_xVKMWP0GS5iSttqgE0NNqKn5YgQNqoyAdopJcsapST__3cF1__bZIKj_1uY0DQqaSl58HYKGz8Mm1JeJZyXPhIShkKyzoqXQ0gN6GfkbPLXiqo1tNX8gRIdYoGz1RYXK_qQ1JAjxSjig2S19vLGPsR871QOTFNLxbWm8ACzrVnYpH-76MrMSA5zYBxtiadJEpk5lUWH2s9O8OXB9jXpummDkJsm-KtwXiEVNocN3JFztgqQME8tAliJa-7gJebGkZ0xfNwxZfJVncI7eblvXOncPgYrWufyhDJHGigQ";
// 获取用户ID(sub)
String userId = GoogleJwtParser.getSubFromToken(token);
System.out.println("用户ID: " + userId);
// 检查Token是否过期(允许10秒误差)
boolean isExpired = GoogleJwtParser.isTokenExpired(token, 10);
System.out.println("Token是否过期: " + isExpired);
// 获取用户邮箱
String email = GoogleJwtParser.getEmailFromToken(token);
System.out.println("用户邮箱: " + email);
// 获取用户姓名
String name = GoogleJwtParser.getNameFromToken(token);
System.out.println("用户姓名: " + name);
}
}

View File

@@ -13,7 +13,7 @@ public interface MyUserDetailsService extends UserDetailsService {
UserDetails loadUserByPhone(String phone, String phoneAreaCode, String smsCode, DeviceInfo deviceInfo, String ipAddress) throws Exception;
UserDetails loadUserByOpenId(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId) throws Exception;
UserDetails loadUserByOpenId(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId, String idToken) throws Exception;
void login(String reqUserName, UserDetails userDetails, LoginTypeEnum loginTypeEnum, DeviceInfo deviceInfo, String smsCode) throws Exception;

View File

@@ -21,7 +21,6 @@ import com.accompany.core.service.account.LoginRecordService;
import com.accompany.core.service.account.UserAppService;
import com.accompany.core.service.common.JedisService;
import com.accompany.core.service.region.RegionNetworkService;
import com.accompany.core.service.user.PhoneBlackService;
import com.accompany.core.service.user.UsersBaseService;
import com.accompany.core.util.I18NMessageSourceUtil;
import com.accompany.email.service.EmailService;
@@ -155,8 +154,8 @@ public class MyUserDetailsServiceImpl implements MyUserDetailsService {
}
@Override
public UserDetails loadUserByOpenId(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId) throws Exception {
Account account = accountManageService.getOrGenAccountByOpenid(openid, type, deviceInfo, ipAddress, unionId);
public UserDetails loadUserByOpenId(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId, String idToken) throws Exception {
Account account = accountManageService.getOrGenAccountByOpenid(openid, type, deviceInfo, ipAddress, unionId, idToken);
if (account == null) {
throw new CustomOAuth2Exception(CustomOAuth2Exception.USER_NOT_EXISTED,
BusiStatus.USER_NOT_EXISTED.getReasonPhrase());

View File

@@ -21,6 +21,7 @@ import com.accompany.core.service.account.ErBanNoService;
import com.accompany.core.service.account.NetEaseService;
import com.accompany.core.service.common.JedisLockService;
import com.accompany.core.service.common.JedisService;
import com.accompany.core.service.user.GoogleOpenidRefService;
import com.accompany.core.service.user.UserCancelRecordService;
import com.accompany.core.service.user.UsersBaseService;
import com.accompany.core.util.MD5;
@@ -74,6 +75,8 @@ public class AccountManageService {
private SmsService smsService;
@Autowired
private EmailService emailService;
@Autowired
private GoogleOpenidRefService googleOpenidRefService;
protected Gson gson = new Gson();
@@ -133,7 +136,7 @@ public class AccountManageService {
}
}
public Account getOrGenAccountByOpenid(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId) throws Exception {
public Account getOrGenAccountByOpenid(String openid, Byte type, DeviceInfo deviceInfo, String ipAddress, String unionId, String idToken) throws Exception {
log.info("getOrGenAccountByOpenid openId:{},type:{},unionId:{}", openid, type, unionId);
final String locKey = RedisKey.lock_register_by_openid.getKey(openid, unionId, String.valueOf(type));
final String lockVal = jedisLockService.lock(locKey, 10 * 1000);
@@ -141,8 +144,16 @@ public class AccountManageService {
if (BlankUtil.isBlank(lockVal)) {
throw new ServiceException(BusiStatus.REQUEST_FAST);
}
Account account = accountService.getAccountByThird(type, unionId,
LoginTypeEnum.GOOGLE.getValue() == type ? deviceInfo.getApp() : null);
boolean googleLogin = LoginTypeEnum.GOOGLE.getValue() == type;
if (googleLogin) {
String sub = googleOpenidRefService.getUnionIdByEmail(openid, idToken);
if (sub != null) {
openid = sub;
unionId = sub;
}
}
Account account = accountService.getAccountByThird(type, unionId, null);
if (account == null) {
checkRegisterLimit(deviceInfo.getDeviceId(), ipAddress);

View File

@@ -51,10 +51,10 @@ public class AccountController extends BaseController {
@RequestMapping("/third/login")
public OAuth2AccessToken login(HttpServletRequest request,
@RequestParam String openid, @RequestParam Integer type,
String unionid, DeviceInfo deviceInfo, AppEnum app) throws Exception {
String unionid, DeviceInfo deviceInfo, AppEnum app, String idToken) throws Exception {
log.info("/acc/third/login? app {} , type {}, unionId {}", app, type, unionid);
String ipAddress = IPUtils.getRealIpAddress(request);
UserDetails userDetails = myUserDetailsService.loadUserByOpenId(openid, type.byteValue(), deviceInfo, ipAddress, unionid);
UserDetails userDetails = myUserDetailsService.loadUserByOpenId(openid, type.byteValue(), deviceInfo, ipAddress, unionid, idToken);
myUserDetailsService.login(null, userDetails, LoginTypeEnum.get(type), deviceInfo, ipAddress, openid, unionid,null);
return createAccessToken(userDetails);