mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 05:00:25 +08:00
refactor:微信认证优化
This commit is contained in:
parent
bbb46a7d9d
commit
2e4fdf551c
@ -3,13 +3,16 @@ package com.youlai.mall.ums.api.entity;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@Accessors(chain = true)
|
||||
public class UmsMember {
|
||||
|
||||
|
||||
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
@ -16,7 +16,7 @@ public interface RemoteUmsMemberService {
|
||||
Result<MemberDTO> loadMemberByOpenid(@PathVariable String openid);
|
||||
|
||||
@PostMapping("/members")
|
||||
Result add(@RequestBody UmsMember umsMember);
|
||||
Result add(@RequestBody UmsMember member);
|
||||
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
http
|
||||
.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
||||
.and()
|
||||
.authorizeRequests().antMatchers("/rsa/publicKey","/oauth/logout").permitAll().anyRequest().authenticated()
|
||||
.authorizeRequests().antMatchers("/rsa/publicKey").permitAll().anyRequest().authenticated()
|
||||
.and()
|
||||
.csrf().disable();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.auth.domain.Oauth2Token;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
import com.youlai.common.core.constant.Constants;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import com.youlai.common.web.exception.BizException;
|
||||
@ -54,13 +55,17 @@ public class AuthController {
|
||||
@ApiImplicitParam(name = "client_secret", defaultValue = "123456", value = "Oauth2客户端秘钥", required = true),
|
||||
@ApiImplicitParam(name = "refresh_token", value = "刷新token"),
|
||||
@ApiImplicitParam(name = "username", defaultValue = "admin", value = "登录用户名"),
|
||||
@ApiImplicitParam(name = "password", defaultValue = "123456", value = "登录密码")
|
||||
@ApiImplicitParam(name = "password", defaultValue = "123456", value = "登录密码"),
|
||||
|
||||
@ApiImplicitParam(name = "code", value = "小程序code"),
|
||||
@ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整用户信息的加密数据"),
|
||||
@ApiImplicitParam(name = "iv", value = "加密算法的初始向量"),
|
||||
})
|
||||
@PostMapping("/token")
|
||||
public Result postAccessToken(
|
||||
@ApiIgnore Principal principal,
|
||||
@ApiIgnore @RequestParam Map<String, String> parameters
|
||||
) throws HttpRequestMethodNotSupportedException {
|
||||
) throws HttpRequestMethodNotSupportedException, WxErrorException {
|
||||
|
||||
String clientId = parameters.get("client_id");
|
||||
|
||||
@ -68,6 +73,11 @@ public class AuthController {
|
||||
throw new BizException("客户端ID不能为空");
|
||||
}
|
||||
|
||||
// 微信小程序端认证处理
|
||||
if(AuthConstants.WEAPP_CLIENT_ID.equals(clientId)){
|
||||
return this.handleForWxAppAuth(principal,parameters);
|
||||
}
|
||||
|
||||
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
|
||||
Oauth2Token oauth2Token = Oauth2Token.builder()
|
||||
.token(oAuth2AccessToken.getValue())
|
||||
@ -78,6 +88,8 @@ public class AuthController {
|
||||
return Result.success(oauth2Token);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@DeleteMapping("/logout")
|
||||
public Result logout(HttpServletRequest request) {
|
||||
String payload = request.getHeader(AuthConstants.JWT_PAYLOAD_KEY);
|
||||
@ -94,4 +106,62 @@ public class AuthController {
|
||||
redisTemplate.opsForValue().set(AuthConstants.TOKEN_BLACKLIST_PREFIX + jti, null, (exp - currentTimeSeconds), TimeUnit.SECONDS);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
private Result handleForWxAppAuth(Principal principal, Map<String, String> parameters) throws WxErrorException, HttpRequestMethodNotSupportedException {
|
||||
|
||||
String code = parameters.get("code");
|
||||
if (StrUtil.isBlank(code)) {
|
||||
throw new BizException("code不能为空");
|
||||
}
|
||||
|
||||
WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
|
||||
String openid = session.getOpenid();
|
||||
String sessionKey = session.getSessionKey();
|
||||
|
||||
Result<MemberDTO> result = remoteUmsMemberService.loadMemberByOpenid(openid);
|
||||
if (!ResultCode.SUCCESS.getCode().equals(result.getCode())) {
|
||||
throw new BizException("获取会员信息失败");
|
||||
}
|
||||
MemberDTO memberDTO = result.getData();
|
||||
String username;
|
||||
if (memberDTO == null) { // 微信授权登录 会员信息不存在时 注册会员
|
||||
String encryptedData = parameters.get("encryptedData");
|
||||
String iv = parameters.get("iv");
|
||||
|
||||
WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
|
||||
if (userInfo == null) {
|
||||
throw new BizException("获取用户信息失败");
|
||||
}
|
||||
UmsMember member = new UmsMember()
|
||||
.setNickname(userInfo.getNickName())
|
||||
.setAvatar(userInfo.getAvatarUrl())
|
||||
.setGender(Integer.valueOf(userInfo.getGender()))
|
||||
.setOpenid(openid)
|
||||
.setUsername(openid)
|
||||
.setPassword(passwordEncoder.encode(openid).replace(AuthConstants.BCRYPT, Strings.EMPTY)) // 加密密码移除前缀加密方式 {bcrypt}
|
||||
.setStatus(Constants.STATUS_NORMAL_VALUE);
|
||||
|
||||
Result res = remoteUmsMemberService.add(member);
|
||||
if (!ResultCode.SUCCESS.getCode().equals(res.getCode())) {
|
||||
throw new BizException("注册会员失败");
|
||||
}
|
||||
username = openid;
|
||||
} else {
|
||||
username = memberDTO.getUsername();
|
||||
}
|
||||
|
||||
parameters.put("username", username);
|
||||
parameters.put("password", username);
|
||||
|
||||
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
|
||||
Oauth2Token oauth2Token = Oauth2Token.builder()
|
||||
.token(oAuth2AccessToken.getValue())
|
||||
.refreshToken(oAuth2AccessToken.getRefreshToken().getValue())
|
||||
.expiresIn(oAuth2AccessToken.getExpiresIn())
|
||||
.build();
|
||||
return Result.success(oauth2Token);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,194 +0,0 @@
|
||||
package com.youlai.auth.controller;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.auth.domain.Oauth2Token;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import com.youlai.common.web.exception.BizException;
|
||||
import com.youlai.mall.ums.api.dto.MemberDTO;
|
||||
import com.youlai.mall.ums.api.entity.UmsMember;
|
||||
import com.youlai.mall.ums.api.feign.RemoteUmsMemberService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Api(tags = "认证中心")
|
||||
@RestController
|
||||
@RequestMapping("/wxoauth")
|
||||
@AllArgsConstructor
|
||||
public class WxOAuthController {
|
||||
|
||||
private TokenEndpoint tokenEndpoint;
|
||||
private RedisTemplate redisTemplate;
|
||||
private WxMaService wxService;
|
||||
private RemoteUmsMemberService remoteUmsMemberService;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
|
||||
@ApiOperation("Oauth2获取token")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "grant_type", defaultValue = "password", value = "授权模式", required = true),
|
||||
@ApiImplicitParam(name = "client_id", defaultValue = "client", value = "Oauth2客户端ID", required = true),
|
||||
@ApiImplicitParam(name = "client_secret", defaultValue = "123456", value = "Oauth2客户端秘钥", required = true),
|
||||
@ApiImplicitParam(name = "refresh_token", value = "刷新token"),
|
||||
|
||||
@ApiImplicitParam(name = "code", value = "小程序code"),
|
||||
@ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整用户信息的加密数据"),
|
||||
@ApiImplicitParam(name = "iv", value = "加密算法的初始向量"),
|
||||
})
|
||||
@PostMapping("/token")
|
||||
public Result postAccessToken(
|
||||
@ApiIgnore Principal principal,
|
||||
@ApiIgnore @RequestParam Map<String, String> parameters
|
||||
) throws HttpRequestMethodNotSupportedException, WxErrorException {
|
||||
|
||||
String clientId = parameters.get("client_id");
|
||||
|
||||
if (StrUtil.isBlank(clientId)) {
|
||||
throw new BizException("客户端ID不能为空");
|
||||
}
|
||||
|
||||
String code = parameters.get("code");
|
||||
if (StrUtil.isBlank(code)) {
|
||||
throw new BizException("code不能为空");
|
||||
}
|
||||
|
||||
WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
|
||||
String openid = session.getOpenid();
|
||||
String sessionKey = session.getSessionKey();
|
||||
|
||||
Result<MemberDTO> result = remoteUmsMemberService.loadMemberByOpenid(openid);
|
||||
if(ResultCode.SUCCESS.getCode().equals(result.getCode())){
|
||||
MemberDTO memberDTO = result.getData();
|
||||
if(memberDTO!=null){
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
WxMaUserInfo userInfo;
|
||||
UmsMember member;
|
||||
if (memberDTO == null || memberDTO.getId() == null) {
|
||||
// 注册会员
|
||||
String encryptedData = parameters.get("encryptedData");
|
||||
String iv = parameters.get("iv");
|
||||
|
||||
userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
|
||||
member = UmsMember.builder()
|
||||
.nickname(userInfo.getNickName())
|
||||
.avatar(userInfo.getAvatarUrl())
|
||||
.gender(Integer.valueOf(userInfo.getGender()))
|
||||
.openid(openid)
|
||||
.username(openid)
|
||||
//.password(passwordEncoder.encode(openid).replace(AuthConstants.BCRYPT, Strings.EMPTY)) // 加密密码移除前缀加密方式 {bcrypt}
|
||||
.build();
|
||||
Result result = remoteUmsMemberService.add(member);
|
||||
if (!ResultCode.SUCCESS.getCode().equals(result.getCode())) {
|
||||
throw new BizException("注册会员失败");
|
||||
}
|
||||
}
|
||||
parameters.put("username", username);
|
||||
parameters.put("password", null);
|
||||
|
||||
|
||||
|
||||
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
|
||||
Oauth2Token oauth2Token = Oauth2Token.builder()
|
||||
.token(oAuth2AccessToken.getValue())
|
||||
.refreshToken(oAuth2AccessToken.getRefreshToken().getValue())
|
||||
.expiresIn(oAuth2AccessToken.getExpiresIn())
|
||||
.build();
|
||||
|
||||
return Result.success(oauth2Token);
|
||||
}
|
||||
|
||||
@DeleteMapping("/logout")
|
||||
public Result logout(HttpServletRequest request) {
|
||||
String payload = request.getHeader(AuthConstants.JWT_PAYLOAD_KEY);
|
||||
JSONObject jsonObject = JSONUtil.parseObj(payload);
|
||||
|
||||
String jti = jsonObject.getStr("jti"); // JWT唯一标识
|
||||
long exp = jsonObject.getLong("exp"); // JWT过期时间戳
|
||||
|
||||
long currentTimeSeconds = System.currentTimeMillis() / 1000;
|
||||
|
||||
if (exp < currentTimeSeconds) { // token已过期,无需加入黑名单
|
||||
return Result.success();
|
||||
}
|
||||
redisTemplate.opsForValue().set(AuthConstants.TOKEN_BLACKLIST_PREFIX + jti, null, (exp - currentTimeSeconds), TimeUnit.SECONDS);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
private WxMaUserInfo handleForWeappAuth(Principal principal, Map<String, String> parameters) {
|
||||
|
||||
try {
|
||||
String code = parameters.get("code");
|
||||
if (StrUtil.isBlank(code)) {
|
||||
throw new BizException("code不能为空");
|
||||
}
|
||||
WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
|
||||
String openid = session.getOpenid();
|
||||
String sessionKey = session.getSessionKey();
|
||||
String username = null;
|
||||
|
||||
MemberDTO memberDTO = remoteUmsMemberService.loadMemberByOpenid(openid);
|
||||
WxMaUserInfo userInfo;
|
||||
if (memberDTO == null || memberDTO.getId() == null) {
|
||||
// 注册会员
|
||||
String encryptedData = parameters.get("encryptedData");
|
||||
String iv = parameters.get("iv");
|
||||
|
||||
userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
|
||||
UmsMember member = UmsMember.builder()
|
||||
.nickname(userInfo.getNickName())
|
||||
.avatar(userInfo.getAvatarUrl())
|
||||
.gender(Integer.valueOf(userInfo.getGender()))
|
||||
.openid(openid)
|
||||
.username(openid)
|
||||
//.password(passwordEncoder.encode(openid).replace(AuthConstants.BCRYPT, Strings.EMPTY)) // 加密密码移除前缀加密方式 {bcrypt}
|
||||
.build();
|
||||
Result result = remoteUmsMemberService.add(member);
|
||||
if (!ResultCode.SUCCESS.getCode().equals(result.getCode())) {
|
||||
throw new BizException("注册会员失败");
|
||||
}
|
||||
username = member.getUsername();
|
||||
} else {
|
||||
userInfo = new WxMaUserInfo();
|
||||
userInfo.setAvatarUrl(memberDTO.getAvatar());
|
||||
userInfo.setNickName(memberDTO.getNickname());
|
||||
username = memberDTO.getUsername();
|
||||
}
|
||||
parameters.put("username", username);
|
||||
parameters.put("password", null);
|
||||
return userInfo;
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
throw new BizException("auth failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,8 @@ import com.youlai.admin.api.dto.UserDTO;
|
||||
import com.youlai.admin.api.feign.RemoteAdminService;
|
||||
import com.youlai.auth.domain.User;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import com.youlai.mall.ums.api.dto.MemberDTO;
|
||||
import com.youlai.mall.ums.api.feign.RemoteUmsMemberService;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -36,18 +38,20 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
User user = null;
|
||||
switch (clientId) {
|
||||
case AuthConstants.ADMIN_CLIENT_ID: // 后台用户
|
||||
UserDTO userDTO = remoteAdminService.loadUserByUsername(username);
|
||||
if (userDTO == null) {
|
||||
Result<UserDTO> userResult = remoteAdminService.loadUserByUsername(username);
|
||||
if (userResult == null || !ResultCode.SUCCESS.getCode().equals(userResult.getCode())) {
|
||||
throw new UsernameNotFoundException("用户不存在");
|
||||
}
|
||||
UserDTO userDTO = userResult.getData();
|
||||
userDTO.setClientId(clientId);
|
||||
user = new User(userDTO);
|
||||
break;
|
||||
case AuthConstants.WEAPP_CLIENT_ID: // 小程序会员
|
||||
MemberDTO memberDTO = remoteUmsMemberService.loadMemberByOpenid(username);
|
||||
if (memberDTO == null) {
|
||||
throw new UsernameNotFoundException("用户不存在");
|
||||
Result<MemberDTO> memberResult = remoteUmsMemberService.loadMemberByOpenid(username);
|
||||
if (memberResult == null || !ResultCode.SUCCESS.getCode().equals(memberResult.getCode())) {
|
||||
throw new UsernameNotFoundException("会员不存在");
|
||||
}
|
||||
MemberDTO memberDTO = memberResult.getData();
|
||||
memberDTO.setClientId(clientId);
|
||||
user = new User(memberDTO);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user