diff --git a/src/main/java/cn/com/tenlion/accesstokenmanager/AccessTokenManager.java b/src/main/java/cn/com/tenlion/accesstokenmanager/AccessTokenManager.java new file mode 100644 index 0000000..3ee8ee6 --- /dev/null +++ b/src/main/java/cn/com/tenlion/accesstokenmanager/AccessTokenManager.java @@ -0,0 +1,53 @@ +package cn.com.tenlion.accesstokenmanager; + + +import cn.com.tenlion.pojo.dtos.carduser.CardUserDTO; +import cn.com.tenlion.pojo.vos.carduser.CardUserVO; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * TODO + * @version 1.0 + * @author LY + * @date 2021/1/27 11:00 + */ +public class AccessTokenManager { + + private static Map cardUserVOMap = new ConcurrentHashMap<>(); + + + private AccessTokenManager(){ + + } + + public static AccessTokenManager getInstance(){ + return tokenManageBuiler.accessTokenInstance; + } + + + public CardUserDTO getKey(String key){ + return cardUserVOMap.get(key); + } + + public void setKey(String key,CardUserDTO cardUserDTO){ + cardUserVOMap.put(key,cardUserDTO); + } + + public void removeKey(String key){ + cardUserVOMap.remove(key); + } + + + public void updateLastActivityTime(String key){ + CardUserDTO dto = this.getKey(key); + dto.setLastActivityTime(System.currentTimeMillis()); + } + + + private static class tokenManageBuiler{ + private static AccessTokenManager accessTokenInstance = new AccessTokenManager(); + } + +} diff --git a/src/main/java/cn/com/tenlion/config/CheckAuth.java b/src/main/java/cn/com/tenlion/config/CheckAuth.java new file mode 100644 index 0000000..ecc18d2 --- /dev/null +++ b/src/main/java/cn/com/tenlion/config/CheckAuth.java @@ -0,0 +1,88 @@ +package cn.com.tenlion.config; + + +import cn.com.tenlion.accesstokenmanager.AccessTokenManager; +import cn.com.tenlion.pojo.dtos.carduser.CardUserDTO; +import cn.com.tenlion.pojo.vos.carduser.CardUserVO; +import cn.com.tenlion.service.carduser.ICardUserService; +import cn.com.tenlion.util.AesUtil; +import com.github.pagehelper.util.StringUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * TODO + * @version 1.0 + * @author LY + * @date 2021/1/27 12:20 + */ +@Component +public class CheckAuth implements HandlerInterceptor { + + @Autowired + private ICardUserService cardUserService; + + /** + * 在请求处理之前进行调用(Controller方法调用之前) + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + try { + String path = request.getServletPath(); + if(path.contains("release")){ + return true; + } + + + String token = request.getHeader("token"); + if(token == null || StringUtil.isEmpty(token)){ +// response.setStatus(response.SC_METHOD_NOT_ALLOWED); +// response.addHeader("msg","token不合法"); + response.sendError(response.SC_METHOD_NOT_ALLOWED,"token不合法"); + return false; + } + + CardUserDTO tokenManage = AccessTokenManager.getInstance().getKey(token); + if(tokenManage != null) { + AccessTokenManager.getInstance().updateLastActivityTime(token); + return true; + }else{ + String aesDecoderToken = AesUtil.aesCommonDecoder(token,token); + CardUserDTO cardUserDTO = cardUserService.getCardUserById(aesDecoderToken); + if(cardUserDTO != null){ + AccessTokenManager.getInstance().setKey(token,cardUserDTO); + AccessTokenManager.getInstance().updateLastActivityTime(token); + } + } + response.setStatus(response.SC_OK); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { + System.out.println("执行了TestInterceptor的postHandle方法"); + } + + /** + * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + System.out.println("执行了TestInterceptor的afterCompletion方法"); + } + + + +} diff --git a/src/main/java/cn/com/tenlion/config/LoginConfig.java b/src/main/java/cn/com/tenlion/config/LoginConfig.java new file mode 100644 index 0000000..aa0fcc6 --- /dev/null +++ b/src/main/java/cn/com/tenlion/config/LoginConfig.java @@ -0,0 +1,31 @@ +package cn.com.tenlion.config; + +import org.apache.catalina.startup.UserConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 拦截器初始化 + * @version 1.0 + * @author LY + * @date 2021/1/27 12:34 + */ +@Configuration +public class LoginConfig implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + //注册TestInterceptor拦截器 + InterceptorRegistration registration = registry.addInterceptor(checkAuth()); + registration.addPathPatterns("/app/**"); //app所有路径都被拦截 + } + + @Bean + private static CheckAuth checkAuth() { + return new CheckAuth(); + } + +} diff --git a/src/main/java/cn/com/tenlion/pojo/dtos/weixinresult/WeiXinAuthResult.java b/src/main/java/cn/com/tenlion/pojo/dtos/weixinresult/WeiXinAuthResult.java new file mode 100644 index 0000000..c4e9495 --- /dev/null +++ b/src/main/java/cn/com/tenlion/pojo/dtos/weixinresult/WeiXinAuthResult.java @@ -0,0 +1,61 @@ +package cn.com.tenlion.pojo.dtos.weixinresult; + + +/** + * TODO + * @version 1.0 + * @author LY + * @date 2021/1/26 16:45 + */ +public class WeiXinAuthResult { + /**用户唯一标识*/ + private String openid; + /**会话密钥*/ + private String session_key; + /**用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回*/ + private String unionid; + /**错误码*/ + private String errcode; + /**错误信息*/ + private String errmsg; + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSession_key() { + return session_key; + } + + public void setSession_key(String session_key) { + this.session_key = session_key; + } + + public String getUnionid() { + return unionid; + } + + public void setUnionid(String unionid) { + this.unionid = unionid; + } + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } +} diff --git a/src/main/java/cn/com/tenlion/util/AesUtil.java b/src/main/java/cn/com/tenlion/util/AesUtil.java new file mode 100644 index 0000000..cc9e19e --- /dev/null +++ b/src/main/java/cn/com/tenlion/util/AesUtil.java @@ -0,0 +1,155 @@ +package cn.com.tenlion.util; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.StringUtils; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.security.*; + +public class AesUtil { + + private static final String IV_STRING = "16-Bytes--String"; + /** + * PKCS#7 + */ + public static final String PKCS_7 = "PKCS7Padding"; + /** + * PKCS#5 + */ + public static final String PKCS_5 = "PKCS5Padding"; + + /** + * AES加密 + * + * @param encodeRule + * @param content + * @return + * @throws Exception + */ + public static String aesEncoder(String encodeRule, String content) throws Exception { + // 1.构造秘钥生成器 + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + // 2.根据编码规则构建秘钥生成器 + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + random.setSeed(encodeRule.getBytes()); + keyGenerator.init(128, random); + // 3.产生堆成秘钥 + SecretKey secretKey = keyGenerator.generateKey(); + // 4.对称秘钥原始数组 + byte[] secretKeyByte = secretKey.getEncoded(); + // 5.生成AES秘钥 + SecretKey key = new SecretKeySpec(secretKeyByte, "AES"); + // 6.初始化密码器 + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + // 8.获取加密内容字节数组 + byte[] contentByte = content.getBytes("UTF-8"); + // 9.加密 + return new String(Base64.encodeBase64(cipher.doFinal(contentByte))); + } + + /** + * AES解密 + * + * @param encodeRule + * @param content + * @return + * @throws Exception + */ + public static String aesDecoder(String encodeRule, String content) throws Exception { + // 1.构建秘钥生成器 + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + // 2.根据编码规则构建秘钥生成器 + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + random.setSeed(encodeRule.getBytes()); + keyGenerator.init(128, random); + // 3.生成对称解密秘钥 + SecretKey secretKey = keyGenerator.generateKey(); + // 4.对称秘钥原始数组 + byte[] secretKeyByte = secretKey.getEncoded(); + // 5.生成AES秘钥 + SecretKey key = new SecretKeySpec(secretKeyByte, "AES"); + // 6.初始化密码器 + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, key); + // 7.要解密内容的字节数组 + byte[] contentByte = Base64.decodeBase64(content); + // 8.解密 + return new String(cipher.doFinal(contentByte), "UTF-8"); + } + + /** + * 通用aes加密,兼容IOS + * + * @param key + * @param content + * @return + * @throws Exception + */ + public static String aesCommonEncoder(String key, String content) throws Exception { + byte[] encryptedBytes = aesCommonEncodeDetail(key, content, IV_STRING.getBytes(), PKCS_5); + return new String(Base64.encodeBase64(encryptedBytes), "UTF-8"); + } + + /** + * 通用aes加密,兼容IOS + * + * @param key + * @param content + * @param paddingType + * @return + * @throws Exception + */ + public static byte[] aesCommonEncodeDetail(String key, String content, byte[] ivBytes, String paddingType) throws Exception { + byte[] byteContent = content.getBytes("UTF-8"); + byte[] enCodeFormat = key.getBytes(); + SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES"); + IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); + if (StringUtils.equals(paddingType, PKCS_7)) { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + Cipher cipher = Cipher.getInstance("AES/CBC/" + paddingType); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + return cipher.doFinal(byteContent); + } + + /** + * aes通用解密,兼容IOS + * + * @param key + * @param content + * @return + * @throws Exception + */ + public static String aesCommonDecoder(String key, String content) throws Exception { + byte[] encryptedBytes = Base64.decodeBase64(content); + byte[] keyBytes = key.getBytes(); + byte[] result = aesCommonDecoderDetail(keyBytes, encryptedBytes, IV_STRING.getBytes(), PKCS_5); + return new String(result, "UTF-8"); + } + + /** + * aes cbc 通用解密 + * + * @param keyBytes 秘钥字节数组 + * @param encryptedBytes 密文字节数组 + * @param ivBytes 向量字节数组 + * @param paddingType 填充类型 + * @return + * @throws Exception + */ + public static byte[] aesCommonDecoderDetail(byte[] keyBytes, byte[] encryptedBytes, byte[] ivBytes, String paddingType) throws Exception { + SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); + IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); + Cipher cipher; + if (StringUtils.equals(paddingType, PKCS_7)) { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + cipher = Cipher.getInstance("AES/CBC/" + paddingType); + cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); + return cipher.doFinal(encryptedBytes); + } +} diff --git a/src/main/java/cn/com/tenlion/util/exception/UpdateException.java b/src/main/java/cn/com/tenlion/util/exception/UpdateException.java new file mode 100644 index 0000000..f45779a --- /dev/null +++ b/src/main/java/cn/com/tenlion/util/exception/UpdateException.java @@ -0,0 +1,31 @@ +package cn.com.tenlion.util.exception; + + +/** + * @ClassName: UpdateException + * @Description: 编辑异常 + * @Author: WangGeng + * @Date: 2019/2/26 5:25 PM + * @Version: 1.0 + **/ +public class UpdateException extends SystemException { + + public UpdateException() { + } + + public UpdateException(String message) { + super(message); + } + + public UpdateException(String message, boolean withMsg) { + super(message, withMsg); + } + + public UpdateException(String message, Throwable cause) { + super(message, cause); + } + + public UpdateException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/cn/com/tenlion/util/vx/WxApiUtil.java b/src/main/java/cn/com/tenlion/util/vx/WxApiUtil.java new file mode 100644 index 0000000..d690b5c --- /dev/null +++ b/src/main/java/cn/com/tenlion/util/vx/WxApiUtil.java @@ -0,0 +1,69 @@ +package cn.com.tenlion.util.vx; + + +import cn.com.tenlion.pojo.dtos.weixinresult.WeiXinAuthResult; +import com.alibaba.druid.util.StringUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +import java.util.HashMap; +import java.util.Map; + +/** + * 微信相关api + * @version 1.0 + * @author LY + * @date 2021/1/27 16:35 + */ +public class WxApiUtil { + + /**微信获取登陆凭证校验 接口*/ + private static String VX_SMALL_ROUTINE_SESSION_KEY = "https://api.weixin.qq.com/sns/jscode2session"; + + + /** + * 获取微信登陆凭证 + * @param code 登录时获取的 code + * @param appId 小程序 appId + * @param secret 小程序 appSecret + * @param grantType 授权类型,此处只需填写 authorization_code + * @return + * @throws Exception + */ + public WeiXinAuthResult weiXinLoginGetAuth(String code,String appId,String secret,String grantType) throws Exception{ + WeiXinAuthResult result = new WeiXinAuthResult(); + result.setErrcode("1"); + if(StringUtils.isEmpty(code) && null != code){ + result.setErrmsg("code 不能为空"); + return result; + } + if(StringUtils.isEmpty(appId) && null != appId){ + result.setErrmsg("appId 不能为空"); + return result; + } + if(StringUtils.isEmpty(secret) && null != secret){ + result.setErrmsg("secret 不能为空"); + return result; + } + if(StringUtils.isEmpty(grantType) && null != grantType){ + result.setErrmsg("grantType不能为空"); + return result; + } + // 配置请求参数 + Map param = new HashMap<>(); + param.put("appid", appId); + param.put("secret", secret); + param.put("js_code", code); + param.put("grant_type", grantType); + String str = WxUtil.doGet(VX_SMALL_ROUTINE_SESSION_KEY, param); + JSONObject json = JSONObject.parseObject(str); + return JSON.toJavaObject(json, WeiXinAuthResult.class); + } + + + + + + + +}