更新登录结构
This commit is contained in:
parent
7d67868635
commit
72c07d2a09
10
api/pom.xml
10
api/pom.xml
@ -35,6 +35,11 @@
|
|||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
<version>1.2.14</version>
|
<version>1.2.14</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.8.9</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@ -72,6 +77,11 @@
|
|||||||
<artifactId>springfox-boot-starter</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
<version>1.57</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package me.xiaoyan.point.api.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.ApiResult;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class AppResponseConfig implements ResponseBodyAdvice<Object> {
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
|
||||||
|
long traceId = 0;
|
||||||
|
List<String> header = serverHttpResponse.getHeaders().get("x-trace-id");
|
||||||
|
if (header != null && header.size() > 0){
|
||||||
|
String xTraceId = header.get(0);
|
||||||
|
if (xTraceId != null) {
|
||||||
|
traceId = Long.valueOf(xTraceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o instanceof String) {
|
||||||
|
return objectMapper.writeValueAsString(ApiResult.success(o).setTraceId(traceId));
|
||||||
|
}
|
||||||
|
if (o instanceof ApiResult) {
|
||||||
|
return ((ApiResult) o).setTraceId(traceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResult.success(o).setTraceId(traceId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package me.xiaoyan.point.api.config;
|
||||||
|
|
||||||
|
import me.xiaoyan.point.api.error.BizException;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.ApiResult;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class ResponseExceptionConfig {
|
||||||
|
@ExceptionHandler(value = BizException.class) // 要捕获的异常类型
|
||||||
|
@ResponseBody
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
public ApiResult bizExceptionHandler(HttpServletRequest req, BizException e) {
|
||||||
|
return ApiResult.error(e.getCode(), e.getMessage());
|
||||||
|
}
|
||||||
|
// 参数异常
|
||||||
|
@ExceptionHandler(value = MethodArgumentNotValidException.class) // 要捕获的异常类型
|
||||||
|
@ResponseBody
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
public ApiResult bizExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException e) {
|
||||||
|
System.out.println(e.getFieldError().getDefaultMessage());
|
||||||
|
return ApiResult.error(1201, e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有单独处理的异常都会被此方法处理
|
||||||
|
@ExceptionHandler(value = Exception.class) // 要捕获的异常类型
|
||||||
|
@ResponseBody
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
public ApiResult exceptionHandler(HttpServletRequest req, Exception e) {
|
||||||
|
return ApiResult.error(-1, "App Internal Error:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,29 @@
|
|||||||
package me.xiaoyan.point.api.controller;
|
package me.xiaoyan.point.api.controller;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.hc.client5.http.classic.HttpClient;
|
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
import me.xiaoyan.point.api.pojo.vo.UserLoginData;
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
import me.xiaoyan.point.api.service.UserInfoService;
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.apache.hc.core5.http.HttpResponse;
|
|
||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
|
||||||
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.Map;
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class WechatController {
|
public class WechatController {
|
||||||
|
@Resource
|
||||||
|
private UserInfoService userInfoService;
|
||||||
|
|
||||||
// code => openid等信息
|
// code => openid等信息
|
||||||
// 使用wx.login获取到的code进行登录,完成登录后下发用户登录凭证
|
// 使用wx.login获取到的code进行登录,完成登录后下发用户登录凭证
|
||||||
@RequestMapping("/wechat/login")
|
@RequestMapping("/wechat/login")
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String login(String code) {
|
public UserInfo login(@Validated @RequestBody UserLoginData data) {
|
||||||
return null;
|
//@NotNull(message = "登录code不能为空")
|
||||||
|
|
||||||
|
return userInfoService.login(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
package me.xiaoyan.point.api.error;
|
package me.xiaoyan.point.api.error;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义的业务异常类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
public class BizException extends RuntimeException {
|
public class BizException extends RuntimeException {
|
||||||
/**
|
|
||||||
* 错误码
|
|
||||||
*/
|
|
||||||
private int code;
|
private int code;
|
||||||
|
|
||||||
public BizException(int code, String message) {
|
private BizException(int code, String message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.code = code;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BizException(Throwable e) {
|
public static BizException create(String message) {
|
||||||
super(e.getMessage());
|
return new BizException(-1, message);
|
||||||
this.code = 500;
|
|
||||||
}
|
}
|
||||||
}
|
public static BizException create(int code,String message) {
|
||||||
|
return new BizException(code, message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import me.xiaoyan.point.api.error.BizException;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@ToString
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ApiResult implements Serializable {
|
||||||
|
private int code;
|
||||||
|
private String message;
|
||||||
|
private Object data;
|
||||||
|
private long traceId;
|
||||||
|
|
||||||
|
public static ApiResult success(Object data) {
|
||||||
|
return new ApiResult(0, "success", data,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiResult error(int code, String message) {
|
||||||
|
return new ApiResult(code, message, null,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiResult error(BizException e) {
|
||||||
|
return new ApiResult(e.getCode(), e.getMessage(), null,0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CodeSessionData implements Serializable {
|
||||||
|
/**
|
||||||
|
* 用户唯一标识
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
/**
|
||||||
|
* 会话密钥,用于签名或解密
|
||||||
|
*/
|
||||||
|
private String sessionKey;
|
||||||
|
/**
|
||||||
|
* 用户在开放平台的唯一标识符
|
||||||
|
*/
|
||||||
|
private String unionid;
|
||||||
|
|
||||||
|
private Integer errcode;
|
||||||
|
|
||||||
|
private String errmsg;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@Builder
|
||||||
|
@ToString
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class WechatUserInfo implements Serializable {
|
||||||
|
private String openId;
|
||||||
|
private String unionId;
|
||||||
|
private String avatarUrl;
|
||||||
|
private String nickName;
|
||||||
|
private Integer gender;
|
||||||
|
private String city;
|
||||||
|
private String province;
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
public UserInfo getUserinfo() {
|
||||||
|
return UserInfo.builder()
|
||||||
|
.province(province).city(city)
|
||||||
|
.nickname(nickName)
|
||||||
|
.headImage(avatarUrl)
|
||||||
|
.openId(openId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserLoginData implements Serializable {
|
||||||
|
@NotEmpty(message = "encryptedData参数不能为空")
|
||||||
|
private String encryptedData;
|
||||||
|
@NotEmpty(message = "iv参数不能为空")
|
||||||
|
private String iv;
|
||||||
|
@NotEmpty(message = "code参数不能为空")
|
||||||
|
private String code;
|
||||||
|
}
|
@ -2,13 +2,14 @@ package me.xiaoyan.point.api.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import me.xiaoyan.point.api.pojo.UserInfo;
|
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.UserLoginData;
|
||||||
|
|
||||||
public interface UserInfoService extends IService<UserInfo> {
|
public interface UserInfoService extends IService<UserInfo> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户的登录
|
* 用户的登录
|
||||||
* @param code 执行wx.login成功后的code
|
* @param data
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public UserInfo login(String code);
|
public UserInfo login(UserLoginData data);
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,14 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.xiaoyan.point.api.util.WechatDecryptDataUtil;
|
||||||
import me.xiaoyan.point.api.error.BizException;
|
import me.xiaoyan.point.api.error.BizException;
|
||||||
import me.xiaoyan.point.api.mapper.PointMapper;
|
|
||||||
import me.xiaoyan.point.api.mapper.UserInfoMapper;
|
import me.xiaoyan.point.api.mapper.UserInfoMapper;
|
||||||
import me.xiaoyan.point.api.pojo.Point;
|
import me.xiaoyan.point.api.pojo.Point;
|
||||||
import me.xiaoyan.point.api.pojo.UserInfo;
|
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.CodeSessionData;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.WechatUserInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.UserLoginData;
|
||||||
import me.xiaoyan.point.api.service.PointRecordService;
|
import me.xiaoyan.point.api.service.PointRecordService;
|
||||||
import me.xiaoyan.point.api.service.PointService;
|
import me.xiaoyan.point.api.service.PointService;
|
||||||
import me.xiaoyan.point.api.service.UserInfoService;
|
import me.xiaoyan.point.api.service.UserInfoService;
|
||||||
@ -21,9 +24,6 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
||||||
@ -63,16 +63,21 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public UserInfo login(String code) {
|
public UserInfo login(UserLoginData data) {
|
||||||
String openId = getOpenIdByCode(code);
|
// 使用code换取登录session相关数据
|
||||||
// TODO 获取用户的基本信息
|
CodeSessionData sessionData = getOpenIdByCode(data.getCode());
|
||||||
|
|
||||||
// 使用openid查询用户信息
|
// 使用openid查询用户信息
|
||||||
final UserInfo userInfo = this.getBaseMapper().selectOneByOpenId(openId);
|
final UserInfo userInfo = this.getBaseMapper().selectOneByOpenId(sessionData.getOpenid());
|
||||||
// 判断用户信息是否存在
|
// 判断用户信息是否存在
|
||||||
if (userInfo == null) {
|
if (userInfo == null) {
|
||||||
|
// 先解码获取用户数据
|
||||||
|
WechatUserInfo wechatUserInfo = WechatDecryptDataUtil.decryptData(
|
||||||
|
data.getEncryptedData(),
|
||||||
|
sessionData.getSessionKey(),
|
||||||
|
data.getIv()
|
||||||
|
);
|
||||||
// 不存在走 第一次登录流程
|
// 不存在走 第一次登录流程
|
||||||
firstLogin(userInfo);
|
firstLogin(wechatUserInfo.getUserinfo());
|
||||||
}
|
}
|
||||||
// 首先
|
// 首先
|
||||||
return userInfo;
|
return userInfo;
|
||||||
@ -88,7 +93,7 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
|||||||
|
|
||||||
// 使用code换取openId
|
// 使用code换取openId
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private String getOpenIdByCode(String code) {
|
private CodeSessionData getOpenIdByCode(String code) {
|
||||||
String url = CODE2SESSION + "?appid=" + app_id + "&secret=" + app_secret
|
String url = CODE2SESSION + "?appid=" + app_id + "&secret=" + app_secret
|
||||||
+ "&js_code=" + code + "&grant_type=authorization_code";
|
+ "&js_code=" + code + "&grant_type=authorization_code";
|
||||||
try (CloseableHttpClient client = HttpClients.createDefault()) {
|
try (CloseableHttpClient client = HttpClients.createDefault()) {
|
||||||
@ -96,11 +101,11 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
|||||||
final CloseableHttpResponse response = (CloseableHttpResponse) client.execute(get);
|
final CloseableHttpResponse response = (CloseableHttpResponse) client.execute(get);
|
||||||
final String content = EntityUtils.toString(response.getEntity());
|
final String content = EntityUtils.toString(response.getEntity());
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
final Map map = mapper.convertValue(content, Map.class);
|
final CodeSessionData data = mapper.convertValue(content, CodeSessionData.class);
|
||||||
if ((Integer) map.get("errcode") != 0) {
|
if (data.getErrcode() != 0) {
|
||||||
throw new BizException(1101, "换取code失败(" + map.get("errmsg") + ")");
|
throw BizException.create(1101, "换取code失败(" + data.getErrmsg() + ")");
|
||||||
}
|
}
|
||||||
return map.get("openid").toString();
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package me.xiaoyan.point.api.util;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.WechatUserInfo;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信工具类
|
||||||
|
*/
|
||||||
|
public class WechatDecryptDataUtil {
|
||||||
|
|
||||||
|
public static WechatUserInfo decryptData(String encryptDataB64, String sessionKeyB64, String ivB64) {
|
||||||
|
String result = new String(
|
||||||
|
decryptOfDiyIV(
|
||||||
|
Base64.getDecoder().decode(encryptDataB64),
|
||||||
|
Base64.getDecoder().decode(sessionKeyB64),
|
||||||
|
Base64.getDecoder().decode(ivB64)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if(!StringUtils.hasLength(result)){
|
||||||
|
throw new RuntimeException("解码失败");
|
||||||
|
}
|
||||||
|
return (new Gson()).fromJson(result,WechatUserInfo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String KEY_ALGORITHM = "AES";
|
||||||
|
private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding";
|
||||||
|
private static Key key;
|
||||||
|
private static Cipher cipher;
|
||||||
|
|
||||||
|
private static void init(byte[] keyBytes) {
|
||||||
|
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
|
||||||
|
int base = 16;
|
||||||
|
if (keyBytes.length % base != 0) {
|
||||||
|
int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
|
||||||
|
byte[] temp = new byte[groups * base];
|
||||||
|
Arrays.fill(temp, (byte) 0);
|
||||||
|
System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
|
||||||
|
keyBytes = temp;
|
||||||
|
}
|
||||||
|
// 初始化
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
// 转化成JAVA的密钥格式
|
||||||
|
key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
|
||||||
|
try {
|
||||||
|
// 初始化cipher
|
||||||
|
cipher = Cipher.getInstance(ALGORITHM_STR, "BC");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密方法
|
||||||
|
*
|
||||||
|
* @param encryptedData 要解密的字符串
|
||||||
|
* @param keyBytes 解密密钥
|
||||||
|
* @param ivs 自定义对称解密算法初始向量 iv
|
||||||
|
* @return 解密后的字节数组
|
||||||
|
*/
|
||||||
|
private static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes, byte[] ivs) {
|
||||||
|
byte[] encryptedText = null;
|
||||||
|
init(keyBytes);
|
||||||
|
try {
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));
|
||||||
|
encryptedText = cipher.doFinal(encryptedData);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return encryptedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
api/src/test/java/me/xiaoyan/point/api/WechatTests.java
Normal file
26
api/src/test/java/me/xiaoyan/point/api/WechatTests.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package me.xiaoyan.point.api;
|
||||||
|
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.WechatUserInfo;
|
||||||
|
import me.xiaoyan.point.api.util.WechatDecryptDataUtil;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class WechatTests {
|
||||||
|
|
||||||
|
|
||||||
|
@DisplayName("解密用户信息")
|
||||||
|
@Test
|
||||||
|
void testDecode(){
|
||||||
|
String encryptedData = "Ezl1S3BHjBeg/HP0Nim/c9eLLYP5L1kgvqSpR+RQYFG6c3Qx0K5U6btEY5IByCw1OsnZ0hKDccNJn3VA/ZgpkxjDODt+XLcph3KqEL6LDU9BLDRFxCI7u+eHBorz5HWYzGITXiuyPb9NWmGAPXwwp0abFqqaycb5u4oii7I/tnh7NIRIcMxAft1YfbVdzQDjraRHFH5hg6Eh4RGSjy6rg1bG/sMecw4+XWM1psTjKBYNwtsG5oxBWja6DniPhmWU6ZwjVMfgJX5Z7wcw2vtmuDPOMCEE1SEcwmTcQ5YKLlPsPBAJhrF3Lxg9oTD1/IlZ";
|
||||||
|
String iv = "ckSRPBLA61WONzUDINIWMg==";
|
||||||
|
|
||||||
|
|
||||||
|
WechatUserInfo wechatUserInfo = WechatDecryptDataUtil.decryptData(
|
||||||
|
"SCK0Ik7THl+USkwTRqTQ9BYGe6rWlXosQ8fWA3I3AsFHTCuPnjbsjFooIEZVcS6mq911XeP5BJJBpPU6A1O3aNuC9L7ebXqTMQX83bVBtaDQySvCIlyyq26xhm8AbWWexl5994NJDpKkNml9ilbYia99bF8bXzXvLCksQQkz82EpZTqztzmCrTdFBZOIrJ+lDnl7rSBWJvVVtoagzgSq2Ux59LcJtxCukIUoZ8fz54//Hm4GhrLucO4zPKTi087f77Pd9K9Rz3LLJ79NMQHHQLtZ38Ws79IKoHBZ7xHXbl3O8xPeTBrrWeHbNfNs1CbOyoe0RwXVjs/fMR9451PeLVM5jg4fj3IDyTFjpx5aUzQRaIrSY/BjVFJoxU/viwQC6LsCBOyXl5uV5h+qIPC5suFbmhl5Q56eU07wbOjNxktEIJsIgbrT+GWRZVPba3dUo+6RoZySxCMA16TRKfuTwjXceV3oNueFdTNyw05s9N43OkrLeKcz1dFeNnpA9DHEVngB1J7MY4RkazdKaWzrld1DjxW6+rk01GgtAr3+H88=",
|
||||||
|
"PKX9EeH6y+pzz8qYrga2jQ==",
|
||||||
|
"Ql/m+Ksll5ziCCZj+07J6g=="
|
||||||
|
|
||||||
|
);
|
||||||
|
System.out.println(wechatUserInfo);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user