feat: 新增微信小程序登录功能及第三方账号绑定表
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package com.youlai.boot.security.provider;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.youlai.boot.security.exception.NeedBindMobileException;
|
||||
import com.youlai.boot.security.model.SysUserDetails;
|
||||
import com.youlai.boot.security.model.UserAuthInfo;
|
||||
import com.youlai.boot.security.model.WechatMiniAuthenticationToken;
|
||||
import com.youlai.boot.system.enums.SocialPlatformEnum;
|
||||
import com.youlai.boot.system.model.entity.UserSocial;
|
||||
import com.youlai.boot.system.service.UserSocialService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 微信小程序认证 Provider
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class WechatMiniAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private final WxMaService wxMaService;
|
||||
private final UserSocialService userSocialService;
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
String code = (String) authentication.getPrincipal();
|
||||
|
||||
if (code == null || code.isEmpty()) {
|
||||
log.warn("微信小程序登录失败:code为空");
|
||||
throw new IllegalArgumentException("code不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 用 code 换取 openid
|
||||
WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code);
|
||||
String openid = session.getOpenid();
|
||||
String sessionKey = session.getSessionKey();
|
||||
|
||||
log.info("微信小程序登录:openid={}", openid);
|
||||
|
||||
// 2. 根据 openid 查询绑定信息
|
||||
UserSocial userSocial = userSocialService.getByPlatformAndOpenid(SocialPlatformEnum.WECHAT_MINI, openid);
|
||||
|
||||
if (userSocial == null) {
|
||||
// 未绑定,抛出异常提示需要绑定手机号
|
||||
log.info("微信小程序登录:用户未绑定手机号,openid={}", openid);
|
||||
throw new NeedBindMobileException(openid, sessionKey);
|
||||
}
|
||||
|
||||
// 3. 获取用户认证信息
|
||||
UserAuthInfo userAuthInfo = userSocialService.getAuthInfoByOpenid(SocialPlatformEnum.WECHAT_MINI, openid);
|
||||
|
||||
if (userAuthInfo == null) {
|
||||
log.warn("微信小程序登录失败:用户不存在,openid={}", openid);
|
||||
throw new UsernameNotFoundException("用户不存在");
|
||||
}
|
||||
|
||||
// 4. 检查用户状态
|
||||
if (ObjectUtil.notEqual(userAuthInfo.getStatus(), 1)) {
|
||||
log.warn("微信小程序登录失败:用户已禁用,username={}", userAuthInfo.getUsername());
|
||||
throw new DisabledException("用户已被禁用");
|
||||
}
|
||||
|
||||
// 5. 更新 session_key
|
||||
userSocialService.updateSessionKey(userSocial.getId(), sessionKey);
|
||||
|
||||
// 6. 构建已认证 Token
|
||||
SysUserDetails userDetails = new SysUserDetails(userAuthInfo);
|
||||
|
||||
log.info("微信小程序登录成功:username={}, openid={}", userAuthInfo.getUsername(), openid);
|
||||
|
||||
return WechatMiniAuthenticationToken.authenticated(userDetails, userDetails.getAuthorities());
|
||||
|
||||
} catch (WxErrorException e) {
|
||||
log.error("微信小程序登录失败:调用微信接口异常,code={}", code, e);
|
||||
throw new IllegalArgumentException("微信登录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return WechatMiniAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user