赞
踩
引入相关依赖
com.auth0
java-jwt
3.9.0
com.github.binarywang
weixin-java-common
3.9.0
com.github.binarywang
weixin-java-miniapp
3.9.0
配置小程序依赖
在yml文件中添加
wx:
mini:
appid: 小程序appid
secret: 小程序secret
新建两个配置文件
@Configuration
@ConfigurationProperties(prefix = "wx.mini")
@Data
public class WechatLoginProperties {
private String appid;
private String secret;
}
@Configuration
@ConditionalOnClass(WxMaService.class)
@EnableConfigurationProperties(WechatLoginProperties.class)
public class WxMaConfiguration {
@Autowired
private WechatLoginProperties wechatLoginProperties;
@Bean
@ConditionalOnMissingBean
public WxMaConfig wxMaConfig(){
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(wechatLoginProperties.getAppid());
config.setSecret(wechatLoginProperties.getSecret());
config.setMsgDataFormat("JSON");
return config;
}
@Bean
public WxMaService wxMaService(WxMaConfig maConfig) {
WxMaService service = new WxMaServiceImpl();
service.setWxMaConfig(maConfig);
return service;
}
}
实现token工具类
@Slf4j
@Component
public class TokenUtil {
// 过期时间6个小时
private static final long EXPIRE_TIME = 6 * 60 * 60 * 1000;
private static final String AUTHORITIES_KEY = "auth";
private static final String SECRET = "KeXu6IgYf7xa";
public static final String CACHE_USERINFO = "miniUserInfo";
@Autowired
private MiniUserInfoMapper miniUserInfoMapper;
@Autowired
private CacheManager cacheManager;
/**
* 校验token是否正确
*
* @param token 密钥
* @return 是否正确
*/
public boolean verify(String token, MiniUserInfo miniUserInfo) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim(AUTHORITIES_KEY, JSONUtil.toJsonStr(miniUserInfo))
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return 用户信息
*/
public MiniUserInfo getUserFromJwt(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
String asString = jwt.getClaim(AUTHORITIES_KEY).asString();
return JSONUtil.toBean(asString, MiniUserInfo.class);
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,EXPIRE_TIME后过期
*
* @return 加密的token
*/
public String sign(MiniUserInfo miniUserInfo) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
return JWT.create()
.withClaim(AUTHORITIES_KEY, JSONUtil.toJsonStr(miniUserInfo))
.withExpiresAt(DateUtil.date(DateUtil.currentSeconds() + EXPIRE_TIME))
.sign(algorithm);
} catch (Exception e) {
return null;
}
}
public String getToken() {
String token;
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
token = request.getHeader("Token");
if (StringUtils.isBlank(token)) {
return "";
}
return token;
}
/**
* 获取用户信息 从加密token中获取
*
* @return MiniUserInfo
*/
public MiniUserInfo getLoginUserWithToken() {
try {
String token = this.getToken();
if (StringUtils.isBlank(token)) {
return null;
}
MiniUserInfo userFromJwt = getUserFromJwt(token);
if (ObjectUtil.isNull(userFromJwt)) {
return null;
}
return userFromJwt;
} catch (Exception e) { //token不存在
return null;
}
}
/**
* 获取用户信息 先走缓存再走数据库
*
* @return MiniUserInfo
*/
public MiniUserInfo getLoginUser() {
try {
log.info("开始->获取用户信息");
String token = this.getToken();
log.info("获取token [{}] ", token);
if (!StringUtils.isNotBlank(token)) {
return null;
}
MiniUserInfo userFromJwt = getUserFromJwt(token);
if (ObjectUtil.isNull(userFromJwt)) {
return null;
}
log.info("解密toke获取用户id : [{}], openId : [{}] ", userFromJwt.getId(), userFromJwt.getOpenId());
if (ObjectUtil.isNull(userFromJwt.getOpenId())) {
return null;
}
MiniUserInfo miniUserInfo;
Cache cache = cacheManager.getCache(CACHE_USERINFO);
if (ObjectUtil.isNull(cache)) {
miniUserInfo = miniUserInfoMapper.selectOne(Wrappers.lambdaQuery().eq(MiniUserInfo::getOpenId, userFromJwt.getOpenId()));
log.info("cache为空从数据库中获取用户信息 : [{}]", miniUserInfo);
} else {
miniUserInfo = cache.get(userFromJwt.getOpenId(), MiniUserInfo.class);
log.info("从缓存获取用户信息 : [{}]", miniUserInfo);
if (ObjectUtil.isNull(miniUserInfo)) {
miniUserInfo = miniUserInfoMapper.selectOne(Wrappers.lambdaQuery().eq(MiniUserInfo::getOpenId, userFromJwt.getOpenId()));
log.info("缓存过期从数据库中获取用户信息 : [{}]", miniUserInfo);
cache.put(userFromJwt.getOpenId(), miniUserInfo);
}
}
if (ObjectUtil.isNull(miniUserInfo)) {
return null;
}
log.info("结束->获取用户信息");
return miniUserInfo;
} catch (Exception e) { //token不存在
return null;
}
}
}
实现登录
创建登录接口
public interface LoginService {
WxLoginResponse loginByWeChat(WxLoginRequest request);
}
实现登录类和方法
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private MiniUserInfoMapper miniUserInfoMapper;
@Autowired
private WxMaService wxService;
@Autowired
private TokenUtil tokenUtil;
@Transactional(rollbackFor = Exception.class)
@Override
public WxLoginResponse loginByWeChat(WxLoginRequest request) {
String token, sessionKey, openId, unionId;
val response = new WxLoginResponse();
try {
WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(request.getCode());
unionId = result.getUnionid();
sessionKey = result.getSessionKey();
openId = result.getOpenid();
} catch (WxErrorException e) {
log.error("获取openid获取失败 : {}", e.getMessage());
throw new NormalException("openid获取失败");
}
if (StringUtils.isNotBlank(openId) || StringUtils.isNotBlank(sessionKey)) {
MiniUserInfo miniUserInfo = miniUserInfoMapper.selectOne(Wrappers.lambdaQuery().eq(MiniUserInfo::getOpenId, openId));
if (ObjectUtil.isNotNull(miniUserInfo)) {
miniUserInfo.setSessionKey(sessionKey);
miniUserInfoMapper.updateById(miniUserInfo);
BeanUtils.copyProperties(miniUserInfo, response);
token = tokenUtil.sign(miniUserInfo);
log.info("登录成功----------生成token : {} ", token);
response.setToken(token);
return response;
}
MiniUserInfo newMiniUser = new MiniUserInfo();
BeanUtils.copyProperties(request, newMiniUser);
newMiniUser.setOpenId(openId)
.setSessionKey(sessionKey)
.setUnionId(unionId)
.setSalt(RandomStringUtils.randomAlphabetic(6));
miniUserInfoMapper.insert(newMiniUser);
token = tokenUtil.sign(newMiniUser);
log.info("注册成功----------生成token : {} ", token);
BeanUtils.copyProperties(newMiniUser, response);
response.setToken(token);
return response;
}
throw new NormalException("用户登录失败");
}
}
暴露登录接口
@Api(value = "/api/login", tags = {"小程序用户登录"})
@RequestMapping("/api/login")
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("/login")
@ApiOperation(value = "小程序登录")
public Result loginByWechat(@RequestBody WxLoginRequest request) {
WxLoginResponse response = loginService.loginByWeChat(request);
return Result.builder().success().data(response).build();
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。