fix: 微信扫码登录重定向问题

This commit is contained in:
TS-QD1 2025-04-21 19:49:40 +08:00
parent c51b14ae1b
commit 6ff58b943e
6 changed files with 145 additions and 176 deletions

View File

@ -1,48 +0,0 @@
package cn.com.tenlion.operator.controller.api.user;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.pojo.vos.UpdateUsernameVO;
import ink.wgink.service.user.service.IUserService;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "企业用户创建员工接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/user-wx-update-username")
public class UserWxUpdateUsernameController {
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@GetMapping("check-phone/{phone}")
public SuccessResultData<String> checkPhone(@PathVariable("phone") String phone) {
UserPO existUserPO = userService.getPOByUsername(phone);
String result = "SUCCESS";
if (existUserPO != null) {
UserExpandPO existUserExpandPO = userExpandService.getPO(existUserPO.getUserId());
if (existUserExpandPO != null) {
if (!StringUtils.isBlank(existUserExpandPO.getWxOpenId())) {
result = "FAIL";
}
}
}
return new SuccessResultData<>(result);
}
}

View File

@ -0,0 +1,31 @@
package cn.com.tenlion.operator.controller.api.user.wx;
import cn.com.tenlion.operator.service.user.wx.UserWxUpdateUsernameService;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.sms.service.sms.ISmsService;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.vos.UpdatePhoneUsernameVO;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "企业用户创建员工接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/user-wx-update-username")
public class UserWxUpdateUsernameController {
@Autowired
private ISmsService smsService;
@Autowired
private UserWxUpdateUsernameService updateUsernameService;
@PostMapping("update-phone")
@CheckRequestBodyAnnotation
public synchronized SuccessResultData<String> checkPhone(@RequestBody UpdatePhoneUsernameVO updatePhoneUsernameVO) {
smsService.checkVerifyCode(updatePhoneUsernameVO.getNewPhone(), updatePhoneUsernameVO.getVerificationCode());
String code = updateUsernameService.updateUsername(updatePhoneUsernameVO.getNewPhone());
return new SuccessResultData<>(code);
}
}

View File

@ -25,8 +25,6 @@ import javax.servlet.http.HttpSession;
@Component
public class LoginWxUpdatePhoneConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> implements ICustomUserSecurityConfig {
@Autowired
private ISmsService smsService;
@Autowired
private BaseProperties baseProperties;
@Autowired
@ -36,23 +34,19 @@ public class LoginWxUpdatePhoneConfig extends SecurityConfigurerAdapter<DefaultS
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@Autowired
private HttpSession httpSession;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
LoginWxUpdatePhoneAuthFilter loginWxUpdatePhoneAuthFilter = new LoginWxUpdatePhoneAuthFilter(smsService);
LoginWxUpdatePhoneAuthFilter loginWxUpdatePhoneAuthFilter = new LoginWxUpdatePhoneAuthFilter(redisTemplate);
loginWxUpdatePhoneAuthFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
loginWxUpdatePhoneAuthFilter.setAuthenticationFailureHandler(new LoginFailureHandler(baseProperties.getLoginFailure()));
LoginWxUpdatePhoneAuthProvider loginWxUpdatePhoneAuthProvider = new LoginWxUpdatePhoneAuthProvider(
userService,
userExpandService,
userDetailsService,
userLoginService,
loginHandler,

View File

@ -1,5 +1,6 @@
package cn.com.tenlion.operator.login.wx.update.phone.auth;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.module.sms.service.sms.ISmsService;
@ -9,6 +10,7 @@ import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.ServletException;
@ -16,94 +18,41 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static cn.com.tenlion.operator.service.user.wx.UserWxUpdateUsernameService.USER_WX_UPDATE_USERNAME_CODE;
public class LoginWxUpdatePhoneAuthFilter extends AbstractAuthenticationProcessingFilter {
private final ISmsService smsService;
private final RedisTemplate<String, String> redisTemplate;
public LoginWxUpdatePhoneAuthFilter(ISmsService smsService) {
super(new AntPathRequestMatcher("/oauth/wx/update/phone", "POST"));
this.smsService = smsService;
public LoginWxUpdatePhoneAuthFilter(RedisTemplate<String, String> redisTemplate) {
super(new AntPathRequestMatcher("/oauth/wx/update/login", "GET"));
this.redisTemplate = redisTemplate;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
PhoneUpdateVO phoneUpdateVO = getPhoneUpdateVO(request);
try {
if (StringUtils.isBlank(phoneUpdateVO.getUserId())) {
throw new BadCredentialsException("userId不能为空");
}
if (StringUtils.isBlank(phoneUpdateVO.getPhone())) {
throw new BadCredentialsException("更新手机号不能为空");
}
if (StringUtils.isBlank(phoneUpdateVO.getSmsCode())) {
throw new BadCredentialsException("手机验证码不能为空");
}
smsService.checkVerifyCode(phoneUpdateVO.getPhone(), phoneUpdateVO.getSmsCode());
} catch (Exception e) {
if (!StringUtils.isBlank(phoneUpdateVO.getErrorRedirectUrl())) {
response.sendRedirect("");
} else {
throw new UserAuthenticationException(e.getMessage());
}
String userId = request.getParameter("userId");
String code = request.getParameter("code");
if (StringUtils.isBlank(userId)) {
throw new UserAuthenticationException("userId不能为空");
}
LoginWxUpdatePhoneAuthToken loginWxUpdatePhoneAuthToken = new LoginWxUpdatePhoneAuthToken(phoneUpdateVO.getUserId(), phoneUpdateVO);
if (StringUtils.isBlank(code)) {
throw new UserAuthenticationException("code不能为空");
}
String jsonString = redisTemplate.opsForValue().get(USER_WX_UPDATE_USERNAME_CODE + userId);
if (StringUtils.isBlank(jsonString)) {
throw new UserAuthenticationException("userId已过期或非法");
}
JSONObject jsonObject = JSONObject.parseObject(jsonString);
String loginCode = jsonObject.getString("loginCode");
if (!StringUtils.equals(loginCode, code)) {
throw new UserAuthenticationException("code错误");
}
String loginUsername = jsonObject.getString("loginUsername");
LoginWxUpdatePhoneAuthToken loginWxUpdatePhoneAuthToken = new LoginWxUpdatePhoneAuthToken(loginUsername, null);
loginWxUpdatePhoneAuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(loginWxUpdatePhoneAuthToken);
}
private PhoneUpdateVO getPhoneUpdateVO(HttpServletRequest request) {
String userId = request.getParameter("userId");
String phone = request.getParameter("phone");
String smsCode = request.getParameter("smsCode");
String errorRedirectUrl = request.getParameter("errorRedirectUrl");
return new PhoneUpdateVO(userId, phone, smsCode, errorRedirectUrl);
}
public static class PhoneUpdateVO {
private String userId;
private String phone;
private String smsCode;
private String errorRedirectUrl;
public PhoneUpdateVO(String userId, String phone, String smsCode, String errorRedirectUrl) {
this.userId = userId;
this.phone = phone;
this.smsCode = smsCode;
this.errorRedirectUrl = errorRedirectUrl;
}
public String getUserId() {
return userId == null ? "" : userId.trim();
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPhone() {
return phone == null ? "" : phone.trim();
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSmsCode() {
return smsCode == null ? "" : smsCode.trim();
}
public void setSmsCode(String smsCode) {
this.smsCode = smsCode;
}
public String getErrorRedirectUrl() {
return errorRedirectUrl == null ? "" : errorRedirectUrl.trim();
}
public void setErrorRedirectUrl(String errorRedirectUrl) {
this.errorRedirectUrl = errorRedirectUrl;
}
}
}

View File

@ -26,21 +26,15 @@ import java.util.Collections;
public class LoginWxUpdatePhoneAuthProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(LoginWxUpdatePhoneAuthProvider.class);
private final IUserService userService;
private final UserExpandServiceImpl userExpandService;
private final UserDetailsService userDetailsService;
private final UserLoginService userLoginService;
private final ILoginHandlerService loginHandler;
private final HttpSession httpSession;
public LoginWxUpdatePhoneAuthProvider(IUserService userService,
UserExpandServiceImpl userExpandService,
UserDetailsService userDetailsService,
public LoginWxUpdatePhoneAuthProvider(UserDetailsService userDetailsService,
UserLoginService userLoginService,
ILoginHandlerService loginHandler,
HttpSession httpSession) {
this.userService = userService;
this.userExpandService = userExpandService;
this.userDetailsService = userDetailsService;
this.userLoginService = userLoginService;
this.loginHandler = loginHandler;
@ -50,40 +44,7 @@ public class LoginWxUpdatePhoneAuthProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
LoginWxUpdatePhoneAuthToken loginWxUpdatePhoneAuthToken = (LoginWxUpdatePhoneAuthToken) authentication;
String userId = (String) authentication.getPrincipal();
LoginWxUpdatePhoneAuthFilter.PhoneUpdateVO phoneUpdateVO = (LoginWxUpdatePhoneAuthFilter.PhoneUpdateVO) authentication.getCredentials();
UserPO userPO = userService.getPO(userId);
if (userPO == null) {
throw new BadCredentialsException("用户不存在");
}
String username = userPO.getUserUsername();
UserPO existUserPO = userService.getPOByUsername(phoneUpdateVO.getPhone());
if (existUserPO == null) {
LOG.debug("更新的手机号用户不存在");
UpdateUsernameVO updateUsernameVO = new UpdateUsernameVO();
updateUsernameVO.setUsername(phoneUpdateVO.getPhone());
updateUsernameVO.setUpdateReason("用户自行修改用户名为手机号");
userService.updateUsername(userPO.getUserId(), updateUsernameVO, false);
} else {
LOG.debug("更新的手机号用户已存在,绑定拓展信息");
UserExpandPO existUserExpandPO = userExpandService.getPO(existUserPO.getUserId());
if (existUserExpandPO == null) {
LOG.debug("更新的手机号用户拓展信息不存在,修改现在的手机号用户拓展信息");
userExpandService.updateUserId(userId, existUserPO.getUserId());
} else {
if (!StringUtils.isBlank(existUserExpandPO.getWxOpenId())) {
throw new BadCredentialsException("手机号已经被绑定");
}
UserExpandPO userExpandPO = userExpandService.getPO(userId);
LOG.debug("更新的手机号用户拓展信息已存在绑定wxOpenid和wxUnionid");
userExpandService.updateWxOpenIdAndUnionId(existUserExpandPO.getUserId(), userExpandPO.getWxOpenId(), userExpandPO.getWxUnionId());
LOG.debug("删除原有账号拓展信息");
userExpandService.deleteByUserIds(Collections.singletonList(userExpandPO.getUserId()));
}
LOG.debug("删除原有账号");
userService.delete(Collections.singletonList(userId));
username = existUserPO.getUserUsername();
}
String username = (String) loginWxUpdatePhoneAuthToken.getPrincipal();
LOG.debug("登录");
httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username);
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);

View File

@ -0,0 +1,82 @@
package cn.com.tenlion.operator.service.user.wx;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.service.account.IAccountService;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.service.role.service.IRoleUserService;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.pojo.vos.UpdateUsernameVO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@Service
public class UserWxUpdateUsernameService extends DefaultBaseService {
public static final String USER_WX_UPDATE_USERNAME_CODE = "user:wx:update:user_id:";
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@Autowired
private IAccountService accountService;
@Autowired
private IRoleUserService roleUserService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
public String updateUsername(String username) {
String userId = securityComponent.getCurrentUser().getUserId();
UserPO userPO = userService.getPO(userId);
UserPO existUserPO = userService.getPOByUsername(username);
if (existUserPO == null) {
LOG.debug("更新的手机号用户不存在");
UpdateUsernameVO updateUsernameVO = new UpdateUsernameVO();
updateUsernameVO.setUsername(username);
updateUsernameVO.setUpdateReason("用户自行修改用户名为手机号");
userService.updateUsername(userPO.getUserId(), updateUsernameVO, false);
} else {
LOG.debug("更新的手机号用户已存在,绑定拓展信息");
UserExpandPO existUserExpandPO = userExpandService.getPO(existUserPO.getUserId());
if (existUserExpandPO == null) {
LOG.debug("更新的手机号用户拓展信息不存在,修改现在的手机号用户拓展信息");
userExpandService.updateUserId(userId, existUserPO.getUserId());
} else {
if (!StringUtils.isBlank(existUserExpandPO.getWxOpenId())) {
throw new UpdateException("手机号已经被绑定,请更换");
}
UserExpandPO userExpandPO = userExpandService.getPO(userId);
LOG.debug("更新的手机号用户拓展信息已存在绑定wxOpenid和wxUnionid");
userExpandService.updateWxOpenIdAndUnionId(existUserExpandPO.getUserId(), userExpandPO.getWxOpenId(), userExpandPO.getWxUnionId());
LOG.debug("删除原有账号拓展信息");
userExpandService.deleteByUserIds(Collections.singletonList(userExpandPO.getUserId()));
}
LOG.debug("删除原有账号");
userService.delete(Collections.singletonList(userId));
LOG.debug("删除account");
accountService.delete(Collections.singletonList(userId));
LOG.debug("删除角色");
roleUserService.deleteByUserId(userId);
}
String uuid = UUIDUtil.get32UUID();
String code = WStringUtil.randomSubStr(uuid, 8);
JSONObject jsonObject = new JSONObject();
jsonObject.put("loginCode", code);
jsonObject.put("loginUsername", username);
redisTemplate.opsForValue().set(USER_WX_UPDATE_USERNAME_CODE + userId, jsonObject.toJSONString(), Duration.ofSeconds(3600));
return code;
}
}