google客户端新sdk兼容登录
google客户端新sdk兼容登录
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
}
|
@@ -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> {
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
|
@@ -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());
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user