这里不做过多解释AES加解密是什么,直接上代码
- 首先导入crypto-js文件
- 写一个aes.js加解密的工具类
import CryptoJS from '...crypto-js'
//密钥 16位
const key = '1111122222333334'
//偏移量 16位
const iv = '0000000000000000'
//加密 ECB模式 不需要iv(偏移量)
function Enctry(word){
return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(word),CryptoJS.enc.Utf8.parse(key),{
iv:CryptoJS.enc.Utf8.parse(iv),
mode:CryptoJS.mode.ECB,
padding:CryptoJS.pad.Pkcs7
})
.toString()
}
//解密 ECB模式 不需要iv(偏移量)
function Decrypt(word){
let decrypted = CryptoJS.AES.decrypt(word,CryptoJS.enc.Utf8.parse(key),{
mode:CryptoJS.mode.ECB,
padding:CryptoJS.pad.Pkcs7
})
return decrypted.toString(CryptoJS.enc.Utf8).toString()
}
export default{
Encrypt,
Decrypt
}
- 在request.js文件中对数据进行加密
//加密开关
import AES from './aes.js'
import CryptoJs from '...crypto-js'
const startAes = true;
service interceptors.request.use(
config => {
if(config.method == 'get'){
//AES加密
if( (config.url.startsWith('开头是否包含请求地址') || (config.url.startsWith('开头是否包含请求地址') ) && startAes == true ){
for(var key in config.params){
config.params[key] = CryptoJS.enc.stringify(CryptoJS.enc.utf8.parse(AES.Encrypt(config.params[key])))
}
//md5签名
config.headers['md5'] = CryptoJS.MD5(JSON.stringifg(config.params)).toString()
//加密标志
config.headers['aes-encrypt'] = 'true'
}
}else if (config.method == 'post'){
config.transformRequest = function(data){
//导出时添加请求头exportFlag:true,这个地方忽略导出,加密导致导出失败
if( (config.url.startsWith('开头是否包含请求地址') || (config.url.startsWith('开头是否包含请求地址') ) && startAes == true && config.headers.exportFlag != true ){
//md5签名
config.headers['md5'] = CryptoJS.MD5(data).toString()
//加密标志
config.headers['aes-encrypt'] = 'true'
//data机密 --这里对参数单个加密,如果对整个body加密后台不容易处理
let da = {}
let dataa = data.split('&')
let ea = []
dataa.forEach(function(element,i){
ea = element.split('=')
da[ea[0]] = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(AES.Encrypt(ea[1])))
})
ea = []
for(var key in da){
ea.push(key+'='+da[key])
}
data = ea.join('&')
}
//
return data
}
}
return config
},
error => {
return Promise.reject(error)
}
)
- 后端数据传输加解密工具类
public class AesEncryptUtils {
//密钥 前后台一致16位
private static final String KEY = "1111122222333334";
//参数分别代表 算法名称/加密模式/数据填充方式
private static final String ALGORITHMESTR = "AES/ECB/PKCS5Padding";
//加密
public static String encrypt(String content,String encryptKey)throws Exception{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMESTR);
cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(encryptkey.getBytes(),"AES"));
byte[] b = cipher.doFinal(content.getBytes("utf-8"));
//采用base64算法进行转码,避免出现中文乱码
return Base64.encodeBaseString(b);
}
//解密
public static String decrypt(String encryptStr,String decryptKey)throws Exception{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMESTR);
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(decryptKey.getBytes(),"AES"));
byte[] b = cipher.doFinal(Base64.decodeBase64(encryptStr));
//采用base64算法进行转码,避免出现中文乱码
return new String(b);
}
}
- 配置过滤器启动
@Configuration
public class FilterConfig{
@Bean
public FilterRegistrationBean filterRegistrationBean (){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean ();
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setFilter(new AesFilter());
filterRegistrationBean.setName("AesFilter");
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
- 异常处理类
public class ExceptionCommonUtils{
pulbic static String getId(){
return uuid.replace("-","");
}
//用来响应信息
public static void responseMessage(HttpServletResponse response,Integer code,String message)throw IOException{
Map<String,Object> map = new HashMap<>();
map.put("code",code);
map.put("message",message);
response.setContentType(text/json;charset=utf-8);
JSONObject fromObject = JSONObject.formObject(map);
PrintWriter pw = response.getWriter();
pw.write(fromObject.toString());
pw.flush();
pw.close();
}
}
- 写一个过滤器进行aes解密
public class AesFilter implements Filter{
//初始化方法和销毁方法在此省略
@Override
public void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain){
try{
HttpServletRequest hsr = (HttpServletRequest)request;
Enumeration<String> headerNames = hsr.getHeaderNames();
while(headerNames.hasMoreElements){
String ele = headerNames.nextElements();
}
//前台是否加密的标记,请求数据是否已经加密
if("true".equals(hsr.getHeader("aes-encrypt"))){
//调用自定义request解析参数
filterChain.doFilter(new AesFilterWrapper((HtppServletRequest)request),response);
}else{
filterChain.doFilter(request,response);
}
}catch(ManageException e){
ExceptionCommonUtils.responseMessage((HtppServletResponse)response,e.getCode,e.getMessage());
}catch(Exception e){
ExceptionCommonUtils.responseMessage((HtppServletResponse)response,e.getCode,e.getMessage());
}
}
}
- 对所有参数进行aes解密
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class AesFilterWrapper extends HttpServletRequestWrapper {
Logger log = LoggerFactory.getLogger(this.getClass());
public AesFilterWrapper (HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String s) {
String str[] = super.getParameterValues(s);
if (str == null) {
return null;
}
int i = str.length;
for (int j = 0; j < i; j++) {
//System.out.println("getParameterValues:"+str[j]);
str[j] = deCrypto(str[j]);
}
return str;
}
@Override
public String getParameter(String s) {
String s1 = super.getParameter(s);
if (s1 == null) {
return null;
} else {
return deCrypto(s1);
}
}
@Override
public Map<String,String[]> getParameterMap(){
HashMap<String,String[]> paramMap = (HashMap<String,String[]>)super.getParameterMap();
paramMap = (HashMap<String,String[]>) paramMap.clone();
for(Iterator iterator = (Iterator) paramMap.entrySet().iterator();iterator.hasNext();){
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) iterator.next();
String[] values = entry.getValue();
for(int i=0;i<values.length;i++){
if(values[i]!=null){
values[i] = deCrypto(values[i]);
}
}
entry.setValue(values);
}
return paramMap;
}
//Aes解密
public String deCrypto(String src){
try{
return URLDecoder.decode(AesEncryptUtils.decrypt(new String(Base64.getDecoder(src))),"UTF-8");
}catch(Exception e){
log.info(e.getMessage());
return src
}
}
}
- 写一个date.properties来定义日期格式
app.date-format-string=yyyy-MM-dd
- 自定义aes加密注解
@Target(value={ElementType.PARAMETER,ElementType.METHOD})
@Retention(value = REtentionPolicy.RUNTIME)
@Documented
public @interface AesEncrypt{
String name() default "name";
}
- 在所需要加密的Controller层方法上加上注解就可以 @AesEncrypt
- 后端对数据进行加密
@ControllerAdvice
@PropertySource("date.properties")
public class AesEncodeAdvice implements ResponseBodyAdvice{
@Value("${app.date-format-string}")
public String dateFormatString;
public String getDateFormatString(){
return dateFormatString;
}
public void setDateFormatString(String dateFormatString){
this.dateFormatString = dateFormatString
}
//是否执行
@Override
public boolean supports(MethodParameter arg0,Class arg1){
//查找带有@AesEncrypt注解的方法进行加密
boolean isSupports = arg0.hasMethodAnnotation(AesEncrypt.class);
return isSupports;
//false 不进行加密
//return false;
}
@Override
public Object beforeBodyWrite(Object params,MethodParameter arg1,MediaType arg2,Class arg3,ServletHttpRequet shresq,ServletHttpResponse shresp){
try{
//是否是后台调用
boolean serverRequest = false;
HtppServletRequest servletRequest = ((HtppServletRequest) shresq.getServletRequest();
Enumeration<String> headerNames = servletRequest.getHeaderNames();
String key = null;
String value = null;
while(headerNames.hasMoreElements()){
key = headerNames.nextElement();
//根据这个请求头 进行不加密
if("请求头key".equals(key)){
serverRequest = true;
}
}
//因加密不会对Date进行处理,这里在加密前对Date进行处理
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(getDateFormatString());
objectMapper.setDateFormat(simpleDateFormat);
String result = "";
if(params instanceof String){
result = (String)params;
}else{
result = objectMapper.writerWithDefaultprettyPrinter().writeValueAsString(params);
}
//后台服务之间的调用,不需要加密
//为了安全起见,这个判断方法不要告诉别人
if(serverRequest){
return params;
}else{
//添加响应头--用于前端解析加密数据
HttpServletResponse serlvetResponse = ((ServletServerHttpResponse)shresp).getServletResponse();
servletResponse.addHeader("aes-encrypt","true");
//调用加密方法
return AesEncryptUtils.encrypt(result);
}
}catch(Exception e){
e.printStackTrace();
}
return params;
}
}
- vue request.js文件中对数据进行解密
service.interceptors.response.use(
response => {
if( (config.url.startsWith('开头是否包含请求地址') || (config.url.startsWith('开头是否包含请求地址') ) && startAes == true && response.headers["aes-encrypt"]==true){
//通过try catch 捕捉异常,防止代码报错
try{
response.data = JSON.parse(AES.Decrypt(response.data));
}catch(d){
}
}
}
)