<?xml version="1.0" encoding="UTF-8"?>
<configuration><include resource="org/springframework/boot/logging/logback/defaults.xml"/><include resource="org/springframework/boot/logging/logback/console-appender.xml"/><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>${LOG_PATH}${LOG_FILE}</File><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${LOG_PATH}daily/${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern><maxHistory>180</maxHistory><maxFileSize>200MB</maxFileSize></rollingPolicy></appender><springProfile name="dev"><root level="INFO"><appender-ref ref="FILE"/><appender-ref ref="CONSOLE"/></root></springProfile><!-- 环境配置 --><springProfile name="test"><root level="INFO"><appender-ref ref="FILE"/><!--<appender-ref ref="CONSOLE"/>--></root></springProfile><!-- 生产环境. --><springProfile name="prod"><root level="INFO"><appender-ref ref="FILE"/></root></springProfile></configuration>

demo/src/test/java/com/monkey/springboot/demo/DemoApplicationTests.java

package com.monkey.springboot.demo;import com.alibaba.fastjson.JSONObject;
import com.monkey.springboot.demo.utils.RSAUtils;
import org.apache.commons.codec.binary.Base64;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.HashMap;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {static String publicKey;static String privateKey;static {try {Map<String, Object> keyMap = RSAUtils.genKeyPair();publicKey = RSAUtils.getPublicKey(keyMap);privateKey = RSAUtils.getPrivateKey(keyMap);System.err.println("公钥: \n\r" + publicKey);System.err.println("私钥: \n\r" + privateKey);} catch (Exception e) {e.printStackTrace();}}@Testpublic void tests() throws Exception {//testJavaRsa();//testSign();test();//testJavaRsa();}static void testSign() throws Exception {System.err.println("私钥加密——公钥解密");String source = "32232";System.out.println("原文字:\r\n" + source);byte[] data = source.getBytes();byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);System.out.println("加密后:\r\n" + new String(encodedData));byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);String target = new String(decodedData);System.out.println("解密后: \r\n" + target);System.err.println("私钥签名——公钥验证签名");String sign = RSAUtils.sign(encodedData, privateKey);System.err.println("签名:\r" + sign);boolean status = RSAUtils.verify(encodedData, publicKey, sign);System.err.println("验证结果:\r" + status);}static void test() throws Exception {System.err.println("公钥加密——私钥解密");String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?";System.out.println("\r加密前文字:\r\n" + source);byte[] sourceBytes = source.getBytes("utf-8");byte[] data = sourceBytes;byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);System.out.println("加密后文字:\r\n" + new String(encodedData));System.out.println("----------------:base64处理:" + Base64.encodeBase64String(encodedData));byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);String target = new String(decodedData);System.out.println("解密后文字: \r\n" + target);}/** 测试自己封装java端加密和解密的方法*/static void testJavaRsa() {String PUBLICKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcd+0zTY9Gn94iqkQJTlxYnEnCeFsLkk0a7hoAvi2B74VzDVV3xH0ZO9RkXvo1SgCB+uzbEWdrgQkzTqyjfTtgOguu3OnkVxIMJF34ibchTY0LWHGxq1m2gLGuVVqrlu1LtdV0X7xo/5zc8Mr+46veWb86kSpqe6rOAm69WWo5GwIDAQAB";String PRIVATEKEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJx37TNNj0af3iKqRAlOXFicScJ4WwuSTRruGgC+LYHvhXMNVXfEfRk71GRe+jVKAIH67NsRZ2uBCTNOrKN9O2A6C67c6eRXEgwkXfiJtyFNjQtYcbGrWbaAsa5VWquW7Uu11XRfvGj/nNzwyv7jq95ZvzqRKmp7qs4Cbr1ZajkbAgMBAAECgYAHp349EkA+DjgJrhah9elilFKvZr/dcwy+koNHIgaL4rG+jRpvP3d3MowTVOocjUA1G5dWqCVNBwTyM5kSbl/nIxSCYwdUoDid4r0JbqkXkTTsIq3euHG8eiWr9rr3SDmwDojWoJEc4liVlfme8dQuMfgxe1QKq7wTrJwCKwbeMQJBAPwpknRPRK8W9hefbbtEu8mlbzUy+ER8Puq6dvS+lnWzJ8n2chJcHRYQFwWpjl4+SZuKeEcDmYmuQ7xuqEIayO0CQQCe2YeaxcU4uuDC45RAwCcMaNw1nDJuA+Gi47lXbroBXoeOiNZunViSZVUgDgrV/Ku6V54TaZIzZ21QFjf7mXEnAkEA7dZwMpAJonOvzfwrzbQ4wyrsx2q5zC68UT1qsdGJrJ48azutwC9tp7+pV0fj5nQtjS1/4Ms+aCQb84ET5rXIyQJAM0m45tgEHZT5DPO94kooUXFp6EVOYwcNyzILnZc6p0aGLhcwZPaYqmvdWEQwa3bxW3D+sPXdJou2V61U1f9s8QJALccvYwwWlCTq1iTmegYk9fOoc+isZKH+Z0YW70kFi94AYEO+utYwmXBEAqQ5VC/bywa1O71xdL4/RGCOSxBf2A==";Map map=new HashMap<String,String>();map.put("key","value");map.put("中文","汉字");String content = JSONObject.toJSONString(map);content = RSAUtils.encryptedDataOnJava(content, PUBLICKEY);System.out.println("加密数据:" + content);System.out.println("解密数据:" + RSAUtils.decryptDataOnJava(content, PRIVATEKEY));}static void testFrontEncrptAndAfterDecrypt() {String PRIVATEKEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIn2zWqU7K/2qm5pOpq5bp9R+3MTnStWTfJU9nC/Vo7UKH9dITPvrELCTK+qlqpx5Fes+l0GY7n6u4n4jyiw4ejsvkZYQ5ww477yLOn2FcoEGuZEwPgSCmfTST0OFUgQqn+/J11k9L92jEHyieE3qmhMkMt0UsVUSJwx/nZxo30ZAgMBAAECgYBD3YHigeuEC4R+14iaf8jo2j0kuGtB3Cxvnlez0otTqw1YyYkBsU49cLKkXvfKVEgM0Ow/QltgKvSBxCE31PrrDka5TygVMqqA/IM7NrDvjUcGLjyoeNmLA8660fWcDxUTlAGN5kxIvUATayVwKVflpWPWu0FPKsWrZustnEo+4QJBAMCmYsWqAKWYMVRXFP3/XGRfio8DV793TOckyBSN9eh8UhgoZyT3u7oeHmDJEwm4aNMHlg1Pcdc6tNsvi1FRCiUCQQC3VNzfF4xOtUgX7vWPL8YVljLuXmy12iVYmg6ofu9l31nwM9FLQ1TRFglvF5LWrIXTQb07PgGd5DJMAQWGsqLlAkAPE7Z9M73TN+L8b8hDzJ1leZi1cpSGdoa9PEKwYR/SrxAZtefEm+LEQSEtf+8OfrEtetWCeyo0pvKKiOEFXytFAkEAgynL/DC0yXsZYUYtmYvshHU5ayFTVagFICbYZeSrEo+BoUDxdI9vl0fU6A5NmBlGhaZ65G+waG5jLc1tTrlvoQJAXBEoPcBNAosiZHQfYBwHqU6mJ9/ZacJh3MtJzGGebfEwJgtln5b154iANqNWXpySBLvkK+Boq7FYRiD83pqmUg==";String data = "FBGU7sQfpSfCgB2hqFuIqkivEUHVRHD8JFdyxYeWqQHsTj9UEuVmvi28n1fOHRwW+3aZD3ttdzfUHWiXD2NErcX/CYs5BtSXT7RcJfWWcXvegq5BBDEAJCADWCRdYnblN+SLUC+ctDXcLw4xmjwAajowSzhCfY/lU3TdnJjO488=";System.out.println("解密数据:" + RSAUtils.decryptDataOnJava(data, PRIVATEKEY));}
}

#AES私钥
aes.private.key=abcdef0123456789
#RSA公私钥
server.private.key=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ9d8zOCDiblFEuDa9ytgEU3iwGETVW1bWwGRfELnC0JFo5m/SS52T0IhB9Tpz54RppkpSfKDEdZ1Kp3BREITQgqAtyiVcX5Eea7+uX3vsV+NGD2kCQGDnPTk98cOpaqQiypfSJFpI/fUFRk6C3Bp9uIG/Z0G9EEx2rTe3Lirw5BAgMBAAECgYBtt2Ga4XvavTWWs1jL6cr4XD/gAHS5gBlgGIWIaMTRoIMd8Ltw0F5GDZngc1gdwvJgks+9L/X6HVczMJOVYVCeKwuBo6JcgK64lhh58wcOlMVcUSydIN4QXbUcWmPnqTsZ1xErTQSdF6ybbNbP02Kf9VL0c/2SEnFx+hlQv4ZoPQJBAM/HxXGisWmA4WMU6WSw5zN78ms85v9nAUb16eHTxEA+Gopn/0kZVdZG7DOudcC9B3h8Q+pDlZ+aY3JL0246K/cCQQDEWfD4W5xmJsr7Jf/G/i00iqMsEoaosBN8EbuyoTqGAauazqdRREv906y8Z43m+UcdyUyyvev+qya2ohDkz1mHAkBhJ5QXEm/KWU0KO1j2kBFLbYVox01r1wot2AbIZXC6aU+XsBEaaRJN41PGxqigusKnf9Nx0rA/tL0TUIlIXUL5AkEAkbima8uhkPZtYmLbJtXwurPBUa4WHg8/Bq8qe/HIOzf2IZgI+PkU5LY51kGMQMT0EJkawPTOtlxTCOvSWd3A9QJBALYU/fjwJsgA9z6/+yV60JX0TmqrS6HBP4MZ72ICDmgfrL7Fy/q+mmMWn952wxA05eqssl7mnXX0PHekdmrd9JU=
client.public.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCE375QvPja/r89w54bglluNWsfDxvqwol7f3+F40TJY/WQtgLjDG7Ry7EzC4Qq4YB7dTMXXKGLar0H8buAFToeqWa8TK9gIsjacPEnnJjN5tGFmDXO7Z1Aev75S8kHbopA+KmsTYgeRXFIkaYkaC6c+60+lFfv8w4fom4L2USw0QIDAQAB

demo/src/main/java/com/monkey/springboot/demo/JSONObjectWrapper.java

package com.monkey.springboot.demo;import com.alibaba.fastjson.JSONObject;public class JSONObjectWrapper {private JSONObject jsonObject;public JSONObjectWrapper(JSONObject jsonObject) {this.jsonObject = jsonObject;}public JSONObject getJSONObject() {return jsonObject;}
}

demo/src/main/java/com/monkey/springboot/demo/WebMvcConfig.java

package com.monkey.springboot.demo;import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.*;import java.util.List;/*** SpringMVC 配置类*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RepeatedlyReadInterceptor()).addPathPatterns("/**");super.addInterceptors(registry);}@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {super.addArgumentResolvers(argumentResolvers);argumentResolvers.add(new MyMethodArgumentResolver());}@Beanpublic FilterRegistrationBean repeatedlyReadFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();RepeatedlyReadFilter repeatedlyReadFilter = new RepeatedlyReadFilter();registration.setFilter(repeatedlyReadFilter);registration.addUrlPatterns("/*");return registration;}
}

demo/src/main/java/com/monkey/springboot/demo/RepeatedlyReadRequestWrapper.java

package com.monkey.springboot.demo;import org.apache.commons.lang3.StringUtils;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;public class RepeatedlyReadRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public RepeatedlyReadRequestWrapper(HttpServletRequest request)throws IOException {super(request);body = readBytes(request.getReader(), "utf-8");}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener listener) {}@Overridepublic int read() throws IOException {return bais.read();}};}/*** 通过BufferedReader和字符编码集转换成byte数组* @param br* @param encoding* @return* @throws IOException*/private byte[] readBytes(BufferedReader br,String encoding) throws IOException{String str = null,retStr="";while ((str = br.readLine()) != null) {retStr += str;}if (StringUtils.isNotBlank(retStr)) {return retStr.getBytes(Charset.forName(encoding));}return null;}
}

demo/src/main/java/com/monkey/springboot/demo/RepeatedlyReadInterceptor.java

package com.monkey.springboot.demo;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;/*** @author zhangmz* @version 1.0.0* @date 2017/09/21*/
public class RepeatedlyReadInterceptor extends HandlerInterceptorAdapter {private static final Logger logger = LoggerFactory.getLogger(RepeatedlyReadInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {/*       if ("POST".equalsIgnoreCase(request.getMethod())) {return super.preHandle(request, response, handler);}else{return false;}*/return  super.preHandle(request, response, handler);//return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

demo/src/main/java/com/monkey/springboot/demo/RepeatedlyReadFilter.java

package com.monkey.springboot.demo;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;/*** 复制请求数据包body* 以提供 拦截器下 可数次获取Body数据包*/
public class RepeatedlyReadFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {ServletRequest requestWrapper = null;if (request instanceof HttpServletRequest) {requestWrapper = new RepeatedlyReadRequestWrapper((HttpServletRequest) request);}if (null == requestWrapper) {chain.doFilter(request, response);} else {chain.doFilter(requestWrapper, response);}}@Overridepublic void destroy() {}
}

demo/src/main/java/com/monkey/springboot/demo/MyMethodArgumentResolver.java

package com.monkey.springboot.demo;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.monkey.springboot.demo.annotation.RequestParam;
import com.monkey.springboot.demo.annotation.SecurityParameter;
import com.monkey.springboot.demo.utils.AesEncryptUtils;
import com.monkey.springboot.demo.utils.RSAUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.annotation.Annotation;
import java.nio.charset.Charset;
import java.util.Map;/*** 获取用户的session dto*/
public class MyMethodArgumentResolver implements HandlerMethodArgumentResolver {private static final String SERVER_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIn2zWqU7K/2qm5pOpq5bp9R+3MTnStWTfJU9nC/Vo7UKH9dITPvrELCTK+qlqpx5Fes+l0GY7n6u4n4jyiw4ejsvkZYQ5ww477yLOn2FcoEGuZEwPgSCmfTST0OFUgQqn+/J11k9L92jEHyieE3qmhMkMt0UsVUSJwx/nZxo30ZAgMBAAECgYBD3YHigeuEC4R+14iaf8jo2j0kuGtB3Cxvnlez0otTqw1YyYkBsU49cLKkXvfKVEgM0Ow/QltgKvSBxCE31PrrDka5TygVMqqA/IM7NrDvjUcGLjyoeNmLA8660fWcDxUTlAGN5kxIvUATayVwKVflpWPWu0FPKsWrZustnEo+4QJBAMCmYsWqAKWYMVRXFP3/XGRfio8DV793TOckyBSN9eh8UhgoZyT3u7oeHmDJEwm4aNMHlg1Pcdc6tNsvi1FRCiUCQQC3VNzfF4xOtUgX7vWPL8YVljLuXmy12iVYmg6ofu9l31nwM9FLQ1TRFglvF5LWrIXTQb07PgGd5DJMAQWGsqLlAkAPE7Z9M73TN+L8b8hDzJ1leZi1cpSGdoa9PEKwYR/SrxAZtefEm+LEQSEtf+8OfrEtetWCeyo0pvKKiOEFXytFAkEAgynL/DC0yXsZYUYtmYvshHU5ayFTVagFICbYZeSrEo+BoUDxdI9vl0fU6A5NmBlGhaZ65G+waG5jLc1tTrlvoQJAXBEoPcBNAosiZHQfYBwHqU6mJ9/ZacJh3MtJzGGebfEwJgtln5b154iANqNWXpySBLvkK+Boq7FYRiD83pqmUg==";@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);// content-type不是json的不处理if (!request.getContentType().contains("application/json")) {return null;}String bodyString = null;RepeatedlyReadRequestWrapper requestWrapper;if (request instanceof RepeatedlyReadRequestWrapper) {requestWrapper = (RepeatedlyReadRequestWrapper) request;bodyString = getBodyString(requestWrapper);}// 利用fastjson转换为对应的类型JSONObjectWrapper jsonObjectWrapper = new JSONObjectWrapper(JSON.parseObject(bodyString));JSONObject jsonObject = jsonObjectWrapper.getJSONObject();// 密文String data = (String) jsonObject.get("requestData");// 加密的ase秘钥String encrypted = (String) jsonObject.get("encrypted");String aseKey = RSAUtils.decryptDataOnJava(encrypted, SERVER_PRIVATE_KEY);String content = AesEncryptUtils.decrypt(data, aseKey);Map<String,String> requestMap = new Gson().fromJson(content,new TypeToken<Map<String,String>>() {}.getType());String value = requestMap.get(parameter.getParameterName());Annotation[] methodAnnotations = parameter.getParameter().getAnnotations();for (int i = 0; i < methodAnnotations.length; i++) {if (methodAnnotations[i] instanceof RequestParam){RequestParam requestParam = (RequestParam) methodAnnotations[i];boolean required = requestParam.required();if (required){if (StringUtils.isEmpty(value)){throw  new RuntimeException("参数异常");}else{return convertIfTypeName(parameter.getParameterType().getName(),value);}}else{if (StringUtils.isEmpty(value)){return convertIfTypeName(parameter.getParameterType().getName(),requestParam.defaultValue());}else{return convertIfTypeName(parameter.getParameterType().getName(),value);}}}}throw  new RuntimeException("参数异常");}@Overridepublic boolean supportsParameter(MethodParameter parameter) {SecurityParameter annotation = parameter.getMethod().getAnnotation(SecurityParameter.class);return annotation != null;//return parameter.hasParameterAnnotation(SecurityParameter.class);}public Object convertIfTypeName(String name,String value){if (StringUtils.isEmpty(name)){throw new RuntimeException("获取参数类型失败");}if (name.equals("java.lang.Double")){return Double.parseDouble(value);}else if(name.equals("java.lang.Integer")){return Integer.parseInt(value);}else{return value;}}/*** 获取请求Body** @param request** @return*/public  String getBodyString(final ServletRequest request) {StringBuilder sb = new StringBuilder();InputStream inputStream = null;BufferedReader reader = null;try {inputStream = cloneInputStream(request.getInputStream());reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return sb.toString();}/*** Description: 复制输入流</br>** @param inputStream** @return</br>*/public  InputStream cloneInputStream(ServletInputStream inputStream) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;try {while ((len = inputStream.read(buffer)) > -1) {byteArrayOutputStream.write(buffer, 0, len);}byteArrayOutputStream.flush();} catch (IOException e) {e.printStackTrace();}InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());return byteArrayInputStream;}
}

demo/src/main/java/com/monkey/springboot/demo/annotation/RequestParam.java

package com.monkey.springboot.demo.annotation;import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.ValueConstants;import java.lang.annotation.*;/*** @author monkey* @desc 请求数据解密* @date 2018/10/25 20:17*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {/*** Alias for {@link #name}.*/@AliasFor("name")String value() default "";/*** The name of the request parameter to bind to.* @since 4.2*/@AliasFor("value")String name() default "";/*** Whether the parameter is required.* <p>Defaults to {@code true}, leading to an exception being thrown* if the parameter is missing in the request. Switch this to* {@code false} if you prefer a {@code null} value if the parameter is* not present in the request.* <p>Alternatively, provide a {@link #defaultValue}, which implicitly* sets this flag to {@code false}.*/boolean required() default true;/*** The default value to use as a fallback when the request parameter is* not provided or has an empty value.* <p>Supplying a default value implicitly sets {@link #required} to* {@code false}.*/String defaultValue() default ValueConstants.DEFAULT_NONE;
}

demo/src/main/java/com/monkey/springboot/demo/utils/RSAUtils.java

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.codec.binary.Base64;import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;import javax.crypto.Cipher;/** */
/*** <p>* RSA公钥/私钥/签名工具包* </p>* <p>* 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)* </p>* <p>* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全* </p>* * @author monkey* @date 2018-10-29*/
public class RSAUtils {/** *//*** 加密算法RSA*/public static final String KEY_ALGORITHM = "RSA";/** *//*** 签名算法*/public static final String SIGNATURE_ALGORITHM = "MD5withRSA";/** *//*** 获取公钥的key*/private static final String PUBLIC_KEY = "RSAPublicKey";/** *//*** 获取私钥的key*/private static final String PRIVATE_KEY = "RSAPrivateKey";/** *//*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/** *//*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/** *//*** RSA 位数 如果采用2048 上面最大加密和最大解密则须填写:  245 256*/private static final int INITIALIZE_LENGTH = 1024;/** *//*** <p>* 生成密钥对(公钥和私钥)* </p>* * @return* @throws Exception*/public static Map<String, Object> genKeyPair() throws Exception {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(INITIALIZE_LENGTH);KeyPair keyPair = keyPairGen.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();Map<String, Object> keyMap = new HashMap<String, Object>(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/** *//*** <p>* 用私钥对信息生成数字签名* </p>* * @param data*            已加密数据* @param privateKey*            私钥(BASE64编码)* * @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(privateK);signature.update(data);return Base64.encodeBase64String(signature.sign());}/** *//*** <p>* 校验数字签名* </p>* * @param data*            已加密数据* @param publicKey*            公钥(BASE64编码)* @param sign*            数字签名* * @return* @throws Exception* */public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {byte[] keyBytes = Base64.decodeBase64(publicKey);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);PublicKey publicK = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(publicK);signature.update(data);return signature.verify(Base64.decodeBase64(sign));}/** *//*** <P>* 私钥解密* </p>* * @param encryptedData*            已加密数据* @param privateKey*            私钥(BASE64编码)* @return* @throws Exception*/public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateK);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}/** *//*** <p>* 公钥解密* </p>* * @param encryptedData*            已加密数据* @param publicKey*            公钥(BASE64编码)* @return* @throws Exception*/public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicK);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}/** *//*** <p>* 公钥加密* </p>* * @param data*            源数据* @param publicKey*            公钥(BASE64编码)* @return* @throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}/** *//*** <p>* 私钥加密* </p>* * @param data*            源数据* @param privateKey*            私钥(BASE64编码)* @return* @throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}/** *//*** <p>* 获取私钥* </p>* * @param keyMap*            密钥对* @return* @throws Exception*/public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {Key key = (Key) keyMap.get(PRIVATE_KEY);return Base64.encodeBase64String(key.getEncoded());}/** *//*** <p>* 获取公钥* </p>* * @param keyMap*            密钥对* @return* @throws Exception*/public static String getPublicKey(Map<String, Object> keyMap) throws Exception {Key key = (Key) keyMap.get(PUBLIC_KEY);return Base64.encodeBase64String(key.getEncoded());}/*** java端公钥加密*/public static String encryptedDataOnJava(String data, String PUBLICKEY) {try {data = Base64.encodeBase64String(encryptByPublicKey(data.getBytes(), PUBLICKEY));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return data;}/*** java端私钥解密*/public static String decryptDataOnJava(String data, String PRIVATEKEY) {String temp = "";try {byte[] rs = Base64.decodeBase64(data);temp = new String(RSAUtils.decryptByPrivateKey(rs, PRIVATEKEY),"UTF-8");} catch (Exception e) {e.printStackTrace();}return temp;}public static void main(String[] args) throws  Exception{
/*      Map<String, Object> stringObjectMap = RSAUtils.genKeyPair();System.out.println(getPrivateKey(stringObjectMap));System.out.println(getPublicKey(stringObjectMap));*/String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ9d8zOCDiblFEuDa9ytgEU3iwGETVW1bWwGRfELnC0JFo5m/SS52T0IhB9Tpz54RppkpSfKDEdZ1Kp3BREITQgqAtyiVcX5Eea7+uX3vsV+NGD2kCQGDnPTk98cOpaqQiypfSJFpI/fUFRk6C3Bp9uIG/Z0G9EEx2rTe3Lirw5BAgMBAAECgYBtt2Ga4XvavTWWs1jL6cr4XD/gAHS5gBlgGIWIaMTRoIMd8Ltw0F5GDZngc1gdwvJgks+9L/X6HVczMJOVYVCeKwuBo6JcgK64lhh58wcOlMVcUSydIN4QXbUcWmPnqTsZ1xErTQSdF6ybbNbP02Kf9VL0c/2SEnFx+hlQv4ZoPQJBAM/HxXGisWmA4WMU6WSw5zN78ms85v9nAUb16eHTxEA+Gopn/0kZVdZG7DOudcC9B3h8Q+pDlZ+aY3JL0246K/cCQQDEWfD4W5xmJsr7Jf/G/i00iqMsEoaosBN8EbuyoTqGAauazqdRREv906y8Z43m+UcdyUyyvev+qya2ohDkz1mHAkBhJ5QXEm/KWU0KO1j2kBFLbYVox01r1wot2AbIZXC6aU+XsBEaaRJN41PGxqigusKnf9Nx0rA/tL0TUIlIXUL5AkEAkbima8uhkPZtYmLbJtXwurPBUa4WHg8/Bq8qe/HIOzf2IZgI+PkU5LY51kGMQMT0EJkawPTOtlxTCOvSWd3A9QJBALYU/fjwJsgA9z6/+yV60JX0TmqrS6HBP4MZ72ICDmgfrL7Fy/q+mmMWn952wxA05eqssl7mnXX0PHekdmrd9JU=";String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfXfMzgg4m5RRLg2vcrYBFN4sBhE1VtW1sBkXxC5wtCRaOZv0kudk9CIQfU6c+eEaaZKUnygxHWdSqdwURCE0IKgLcolXF+RHmu/rl977FfjRg9pAkBg5z05PfHDqWqkIsqX0iRaSP31BUZOgtwafbiBv2dBvRBMdq03ty4q8OQQIDAQAB";String data = encryptedDataOnJava("aaa", publicKey);String java = decryptDataOnJava(data, privateKey);System.out.println(java);}
}

demo/src/main/java/com/monkey/springboot/demo/annotation/RsaSecurityParameter.java

import org.springframework.web.bind.annotation.Mapping;import java.lang.annotation.*;/*** @author monkey* @desc 请求RSA数据解密* @date 2018/10/25 20:17*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
public @interface RsaSecurityParameter {/*** 入参是否解密,默认解密*/boolean inDecode() default true;/*** 出参是否加密,默认加密*/boolean outEncode() default true;
}

demo/src/main/java/com/monkey/springboot/demo/annotation/SecurityParameter.java

import org.springframework.web.bind.annotation.Mapping;import java.lang.annotation.*;/*** @author monkey* @desc 请求混合数据解密* @date 2018/10/25 20:17*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
/*@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)*/
public @interface SecurityParameter {/*** 入参是否解密,默认解密*/boolean inDecode() default true;/*** 出参是否加密,默认加密*/boolean outEncode() default true;
}

demo/src/main/java/com/monkey/springboot/demo/annotation/AesSecurityParameter.java

package com.monkey.springboot.demo.annotation;import org.springframework.web.bind.annotation.Mapping;import java.lang.annotation.*;/*** @author monkey* @desc 请求Aes数据解密* @date 2018/10/25 20:17*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
public @interface AesSecurityParameter {/*** 入参是否解密,默认解密*/boolean inDecode() default true;/*** 出参是否加密,默认加密*/boolean outEncode() default true;
}

demo/src/main/java/com/monkey/springboot/demo/advice/DecodeRequestBodyAdvice.java

package com.monkey.springboot.demo.advice;import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.monkey.springboot.demo.HttpRequest;
import com.monkey.springboot.demo.annotation.AesSecurityParameter;
import com.monkey.springboot.demo.annotation.RsaSecurityParameter;
import com.monkey.springboot.demo.annotation.SecurityParameter;
import com.monkey.springboot.demo.utils.AesEncryptUtils;
import com.monkey.springboot.demo.utils.RSAUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.Map;/*** @author monkey* @desc 请求数据解密* @date 2018/10/29 20:17*/
@ControllerAdvice
public class DecodeRequestBodyAdvice implements RequestBodyAdvice {private static final Logger logger = LoggerFactory.getLogger(DecodeRequestBodyAdvice.class);@Value("${server.private.key}")private String SERVER_PRIVATE_KEY;@Value("${aes.private.key}")private String AES_PRIVATE_KEY;@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return true;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return body;}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {try {if (methodParameter.getMethod().isAnnotationPresent(AesSecurityParameter.class)) {//获取注解配置的包含和去除字段AesSecurityParameter serializedField = methodParameter.getMethodAnnotation(AesSecurityParameter.class);//入参是否需要解密if(serializedField.inDecode()){logger.info("注解AesSecurityParameter,对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");return new AesHttpInputMessage(inputMessage);}}if (methodParameter.getMethod().isAnnotationPresent(RsaSecurityParameter.class)) {//获取注解配置的包含和去除字段RsaSecurityParameter serializedField = methodParameter.getMethodAnnotation(RsaSecurityParameter.class);//入参是否需要解密if(serializedField.inDecode()){logger.info("注解RsaSecurityParameter,对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");return new RsaHttpInputMessage(inputMessage);}}if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {//获取注解配置的包含和去除字段SecurityParameter serializedField = methodParameter.getMethodAnnotation(SecurityParameter.class);//入参是否需要解密if(serializedField.inDecode()){logger.info("注解SecurityParameter,对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");return new MyHttpInputMessage(inputMessage);}}return inputMessage;} catch (Exception e) {e.printStackTrace();logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:"+e.getMessage());return inputMessage;}}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return body;}class MyHttpInputMessage implements HttpInputMessage {private HttpHeaders headers;private InputStream body;public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {this.headers = inputMessage.getHeaders();this.body = IOUtils.toInputStream(easpString(IOUtils.toString(inputMessage.getBody(),"utf-8")));}@Overridepublic InputStream getBody() throws IOException {return body;}@Overridepublic HttpHeaders getHeaders() {return headers;}/**** @param requestData* @return*/public String easpString(String requestData) {if(requestData != null && !requestData.equals("")){Map<String,String> requestMap = new Gson().fromJson(requestData,new TypeToken<Map<String,String>>() {}.getType());// 密文String data = requestMap.get("requestData");// 加密的ase秘钥String encrypted = requestMap.get("encrypted");if(StringUtils.isEmpty(data) || StringUtils.isEmpty(encrypted)){throw new RuntimeException("参数【requestData】缺失异常!");}else{String content = null ;String aseKey = null;try {aseKey = RSAUtils.decryptDataOnJava(encrypted,SERVER_PRIVATE_KEY);}catch (Exception e){throw  new RuntimeException("参数【aseKey】解析异常!");}try {content  = AesEncryptUtils.decrypt(data, aseKey);}catch (Exception e){throw  new RuntimeException("参数【content】解析异常!");}if (StringUtils.isEmpty(content) || StringUtils.isEmpty(aseKey)){throw  new RuntimeException("参数【requestData】解析参数空指针异常!");}return content;}}throw new RuntimeException("参数【requestData】不合法异常!");}}class RsaHttpInputMessage implements HttpInputMessage {private HttpHeaders headers;private InputStream body;public RsaHttpInputMessage(HttpInputMessage inputMessage) throws Exception {this.headers = inputMessage.getHeaders();this.body = IOUtils.toInputStream(easpString(IOUtils.toString(inputMessage.getBody(),"utf-8")));}@Overridepublic InputStream getBody() throws IOException {return body;}@Overridepublic HttpHeaders getHeaders() {return headers;}/**** @param requestData* @return*/public String easpString(String requestData) {if(requestData != null && !requestData.equals("")){Map<String,String> requestMap = new Gson().fromJson(requestData,new TypeToken<Map<String,String>>() {}.getType());// 密文String data = requestMap.get("requestData");if(StringUtils.isEmpty(data)){throw new RuntimeException("参数【requestData】缺失异常!");}else{String content = null ;try {content = RSAUtils.decryptDataOnJava(data,SERVER_PRIVATE_KEY);}catch (Exception e){throw  new RuntimeException("参数【aseKey】解析异常!");}try {}catch (Exception e){throw  new RuntimeException("参数【content】解析异常!");}if (StringUtils.isEmpty(content)){throw  new RuntimeException("参数【requestData】解析参数空指针异常!");}return content;}}throw new RuntimeException("参数【requestData】不合法异常!");}}class AesHttpInputMessage implements HttpInputMessage {private HttpHeaders headers;private InputStream body;public AesHttpInputMessage(HttpInputMessage inputMessage) throws Exception {this.headers = inputMessage.getHeaders();this.body = IOUtils.toInputStream(easpString(IOUtils.toString(inputMessage.getBody(),"utf-8")));}@Overridepublic InputStream getBody() throws IOException {return body;}@Overridepublic HttpHeaders getHeaders() {return headers;}/**** @param requestData* @return*/public String easpString(String requestData) {if(requestData != null && !requestData.equals("")){Map<String,String> requestMap = new Gson().fromJson(requestData,new TypeToken<Map<String,String>>() {}.getType());// 密文String data = requestMap.get("requestData");if(StringUtils.isEmpty(data)){throw new RuntimeException("参数【requestData】缺失异常!");}else{String content = null ;try {content  = AesEncryptUtils.decrypt(data, AES_PRIVATE_KEY);}catch (Exception e){throw  new RuntimeException("参数【content】解析异常!");}if (StringUtils.isEmpty(content)){throw  new RuntimeException("参数【requestData】解析参数空指针异常!");}return content;}}throw new RuntimeException("参数【requestData】不合法异常!");}}
}

demo/src/main/java/com/monkey/springboot/demo/advice/EncodeResponseBodyAdvice.java

package com.monkey.springboot.demo.advice;import com.fasterxml.jackson.databind.ObjectMapper;
import com.monkey.springboot.demo.annotation.AesSecurityParameter;
import com.monkey.springboot.demo.annotation.RsaSecurityParameter;
import com.monkey.springboot.demo.annotation.SecurityParameter;
import com.monkey.springboot.demo.utils.AesEncryptUtils;
import com.monkey.springboot.demo.utils.RSAUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.util.HashMap;
import java.util.Map;
import java.util.Random;/*** @author monkey* @desc 返回数据加密* @date 2018/10/25 20:17*/
@ControllerAdvice
public class EncodeResponseBodyAdvice implements ResponseBodyAdvice {private final static Logger logger = LoggerFactory.getLogger(EncodeResponseBodyAdvice.class);@Value("${client.public.key}")private String CLIENT_PUBLIC_KEY;@Value("${aes.private.key}")private String AES_PRIVATE_KEY;@Overridepublic boolean supports(MethodParameter methodParameter, Class aClass) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {if (methodParameter.getMethod().isAnnotationPresent(AesSecurityParameter.class)) {//获取注解配置的包含和去除字段AesSecurityParameter serializedField = methodParameter.getMethodAnnotation(AesSecurityParameter.class);//出参是否需要加密if (serializedField.outEncode()){logger.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");return encodeAes(methodParameter,body);}}if (methodParameter.getMethod().isAnnotationPresent(RsaSecurityParameter.class)) {//获取注解配置的包含和去除字段RsaSecurityParameter serializedField = methodParameter.getMethodAnnotation(RsaSecurityParameter.class);//出参是否需要加密if (serializedField.outEncode()){logger.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");return encodeRsa(methodParameter,body);}}if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {//获取注解配置的包含和去除字段SecurityParameter serializedField = methodParameter.getMethodAnnotation(SecurityParameter.class);//出参是否需要加密if (serializedField.outEncode()){logger.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");return encodeAesRsa(methodParameter,body);}}return body;}/*** AES加密* @param methodParameter* @param body* @return*/private Object encodeAes(MethodParameter methodParameter,Object body){ObjectMapper objectMapper = new ObjectMapper();try {String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);// aes加密String requestData = AesEncryptUtils.encrypt(result, AES_PRIVATE_KEY);Map<String, String> map = new HashMap<>();map.put("requestData", requestData);return map;} catch (Exception e) {e.printStackTrace();logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:" + e.getMessage());}return body;}/*** RSA加密* @param methodParameter* @param body* @return*/private Object encodeRsa(MethodParameter methodParameter,Object body){ObjectMapper objectMapper = new ObjectMapper();try {String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);// rsa加密String requestData = RSAUtils.encryptedDataOnJava(result, CLIENT_PUBLIC_KEY);Map<String, String> map = new HashMap<>();map.put("requestData", requestData);return map;} catch (Exception e) {e.printStackTrace();logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:" + e.getMessage());}return body;}/*** 混合加密* @return*/private Object encodeAesRsa(MethodParameter methodParameter,Object body){ObjectMapper objectMapper = new ObjectMapper();try {String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);// 生成aes秘钥String aseKey = getRandomString(16);// rsa加密String encrypted = RSAUtils.encryptedDataOnJava(aseKey, CLIENT_PUBLIC_KEY);// aes加密String requestData = AesEncryptUtils.encrypt(result, aseKey);Map<String, String> map = new HashMap<>();map.put("encrypted", encrypted);map.put("requestData", requestData);return map;} catch (Exception e) {e.printStackTrace();logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:" + e.getMessage());}return body;}/*** 创建指定位数的随机字符串* @param length 表示生成字符串的长度* @return 字符串*/public static String getRandomString(int length) {String base = "abcdefghijklmnopqrstuvwxyz0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}public static void main(String[] args) {System.out.println(getRandomString(16));}
}

demo/src/main/java/com/monkey/springboot/demo/controller/TestController.java

/*** Copyright (C), 2015-2018, XXX有限公司* FileName: TestController* Author:   44637* Date:     2018/10/24 19:20* Description: 测试加解密* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.monkey.springboot.demo.controller;import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.monkey.springboot.demo.HttpRequest;
import com.monkey.springboot.demo.annotation.AesSecurityParameter;
import com.monkey.springboot.demo.annotation.MyLog;
import com.monkey.springboot.demo.annotation.RsaSecurityParameter;
import com.monkey.springboot.demo.annotation.SecurityParameter;
import com.monkey.springboot.demo.domain.Persion;
import com.monkey.springboot.demo.utils.BadWordUtil;
import com.monkey.springboot.demo.utils.SendEmailUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** 〈一句话功能简述〉<br>* 〈测试加解密和谷歌验证〉** @author 44637* @create 2018/10/24* @since 1.0.0*/
@Controller
public class TestController {private static final Logger logger = LoggerFactory.getLogger(TestController.class);@Autowiredprivate SendEmailUtils sendEmailUtils;// 跳转rsa页面@GetMapping("/rsa")public Object getRsa() {return "rsa";}// 跳转aes页面@GetMapping("/aes")public Object getAes() {
return "aes";}// 跳转rsa+aes页面@RequestMapping("/rsaAes")public Object getRsaAes() {return "rsaAes";}// 跳转summary页面@RequestMapping("/summary")public Object getSummary() {return "summary";}// 跳转recaptchaV2页面@RequestMapping("/recaptchaV2")public Object getRecaptchaV2() {return "recaptchaV2";}// 跳转recaptchaV3页面@RequestMapping("/recaptchaV3")public Object getRecaptchaV3() {return "recaptchaV3";}/*** AES加密测试* @return object*/@RequestMapping("/testAesEncrypt")@ResponseBody@AesSecurityParameterpublic Persion testAesEncrypt(@RequestBody Persion info) {return info;}/*** RSA加密测试* @return object*/@RequestMapping("/testRsaEncrypt")@ResponseBody@RsaSecurityParameterpublic Persion testRsaEncrypt(@RequestBody Persion info) {return info;}/*** RSA+AES双重加密测试* @return object*/@RequestMapping("/testEncrypt")@ResponseBody@SecurityParameterpublic Persion testEncrypt(@RequestBody Persion info) {return info;}/*** 综合测试* @param persion* @return*/@MyLog(value = "综合测试记录")@RequestMapping(value = "/check", method = RequestMethod.POST)@SecurityParameter@ResponseBodypublic Persion check(@RequestBody Persion persion) {try {Map<String, Object> checkMap = new HashMap<>();// 私钥checkMap.put("secret", "6Lc7qXcUAAAAAH_3fhtzGp3MME3O2LC4QO3phFHS");checkMap.put("response", persion.getCode());String json = HttpRequest.sendPost("https://www.recaptcha.net/recaptcha/api/siteverify", checkMap, "UTF-8");Map<String, Object> resultMap = new Gson().fromJson(json, new TypeToken<Map<String, Object>>() {}.getType());System.out.println(json);boolean resultCode = (boolean) resultMap.get("success");if (!resultCode) {String errorCode = resultMap.get("error-codes").toString();String errorInfo = null;if (StringUtils.isEmpty(errorCode)) {errorInfo = errorCode;} else if (errorCode.contains("missing-input-secret")) {errorInfo = "私钥参数丢失了。";} else if (errorCode.contains("invalid-input-secret")) {errorInfo = "私钥参数无效或格式不正确。";} else if (errorCode.contains("missing-input-response")) {errorInfo = "响应参数缺失。";} else if (errorCode.contains("invalid-input-response")) {errorInfo = "响应参数无效或格式不正确。";} else if (errorCode.contains("bad-request")) {errorInfo = "请求无效或格式不正确。";}logger.info("对方法method :【check】进行图形验证不通过,返回结果是: " + errorInfo);}return persion;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("参数【g-recaptcha-response】验证过程中异常!");}}@MyLog(value = "谷歌recaptchaV2验证记录")@RequestMapping("/checkV2")@ResponseBodypublic String checkV2(String token) {Map<String, Object> map = new HashMap<>();// 私钥map.put("secret", "6Lc7qXcUAAAAAH_3fhtzGp3MME3O2LC4QO3phFHS");map.put("response", token);String json = HttpRequest.sendPost("https://www.recaptcha.net/recaptcha/api/siteverify", map, "UTF-8");return json;}@MyLog(value = "谷歌recaptchaV3验证记录")@RequestMapping("/checkV3")@ResponseBodypublic String checkV3(String token) {Map<String, Object> map = new HashMap<>();// 私钥map.put("secret", "6LdBgIoUAAAAAMyFObm3oUzGUot7VJwfMCtu15fr");map.put("response", token);String json = HttpRequest.sendPost("https://www.recaptcha.net/recaptcha/api/siteverify", map, "UTF-8");return json;}@MyLog(value = "敏感词验证记录")@RequestMapping("/checkStr")@ResponseBodypublic String checkStr(String str) {System.out.println("替换敏感词: "+BadWordUtil.replaceBadWord(str, 2, "*"));System.out.println("是否包含敏感词: "+BadWordUtil.isContaintBadWord(str, 2));Set<String> set = BadWordUtil.getBadWord(str, 2);System.out.println("敏感词汇个数: "+set.size());System.out.println("敏感词汇: "+BadWordUtil.getBadWord(str, 2));return str;}@MyLog(value = "发送邮件记录")@GetMapping("/sendEmail")@ResponseBodypublic void sendEmail(String email) throws Exception {sendEmailUtils.send(email);}
}

demo/src/main/java/com/monkey/springboot/demo/utils/AesEncryptUtils.java

package com.monkey.springboot.demo.utils;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.apache.commons.codec.binary.Base64;import java.util.HashMap;
import java.util.Map;/*** 前后端数据传输加密工具类* @author pibigstar**/
public class AesEncryptUtils {//可配置到Constant中,并读取配置文件注入private static final String KEY = "abcdef0123456789";//参数分别代表 算法名称/加密模式/数据填充方式private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";/*** 加密* @param content 加密的字符串* @param encryptKey key值* @return* @throws Exception*/public static String encrypt(String content, String encryptKey) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);Cipher cipher = Cipher.getInstance(ALGORITHMSTR);cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));byte[] b = cipher.doFinal(content.getBytes("utf-8"));// 采用base64算法进行转码,避免出现中文乱码return Base64.encodeBase64String(b);}/*** 解密* @param encryptStr 解密的字符串* @param decryptKey 解密的key值* @return* @throws Exception*/public static String decrypt(String encryptStr, String decryptKey) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);Cipher cipher = Cipher.getInstance(ALGORITHMSTR);cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));// 采用base64算法进行转码,避免出现中文乱码byte[] encryptBytes = Base64.decodeBase64(encryptStr);byte[] decryptBytes = cipher.doFinal(encryptBytes);return new String(decryptBytes);}public static String encrypt(String content) throws Exception {return encrypt(content, KEY);}public static String decrypt(String encryptStr) throws Exception {return decrypt(encryptStr, KEY);}public static void main(String[] args) throws Exception {Map map=new HashMap<String,String>();map.put("key","value");map.put("中文","汉字");String content = JSONObject.toJSONString(map);System.out.println("加密前:" + content);String encrypt = encrypt(content, KEY);System.out.println("加密后:" + encrypt);String decrypt = decrypt(encrypt, KEY);System.out.println("解密后:" + decrypt);}
}

application.properties

#RSA公私钥
server.private.key=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ9d8zOCDiblFEuDa9ytgEU3iwGETVW1bWwGRfELnC0JFo5m/SS52T0IhB9Tpz54RppkpSfKDEdZ1Kp3BREITQgqAtyiVcX5Eea7+uX3vsV+NGD2kCQGDnPTk98cOpaqQiypfSJFpI/fUFRk6C3Bp9uIG/Z0G9EEx2rTe3Lirw5BAgMBAAECgYBtt2Ga4XvavTWWs1jL6cr4XD/gAHS5gBlgGIWIaMTRoIMd8Ltw0F5GDZngc1gdwvJgks+9L/X6HVczMJOVYVCeKwuBo6JcgK64lhh58wcOlMVcUSydIN4QXbUcWmPnqTsZ1xErTQSdF6ybbNbP02Kf9VL0c/2SEnFx+hlQv4ZoPQJBAM/HxXGisWmA4WMU6WSw5zN78ms85v9nAUb16eHTxEA+Gopn/0kZVdZG7DOudcC9B3h8Q+pDlZ+aY3JL0246K/cCQQDEWfD4W5xmJsr7Jf/G/i00iqMsEoaosBN8EbuyoTqGAauazqdRREv906y8Z43m+UcdyUyyvev+qya2ohDkz1mHAkBhJ5QXEm/KWU0KO1j2kBFLbYVox01r1wot2AbIZXC6aU+XsBEaaRJN41PGxqigusKnf9Nx0rA/tL0TUIlIXUL5AkEAkbima8uhkPZtYmLbJtXwurPBUa4WHg8/Bq8qe/HIOzf2IZgI+PkU5LY51kGMQMT0EJkawPTOtlxTCOvSWd3A9QJBALYU/fjwJsgA9z6/+yV60JX0TmqrS6HBP4MZ72ICDmgfrL7Fy/q+mmMWn952wxA05eqssl7mnXX0PHekdmrd9JU=
client.public.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCE375QvPja/r89w54bglluNWsfDxvqwol7f3+F40TJY/WQtgLjDG7Ry7EzC4Qq4YB7dTMXXKGLar0H8buAFToeqWa8TK9gIsjacPEnnJjN5tGFmDXO7Z1Aev75S8kHbopA+KmsTYgeRXFIkaYkaC6c+60+lFfv8w4fom4L2USw0QIDAQAB
#AES私钥
aes.private.key=abcdef0123456789#邮箱服务器地址
#spring.mail.host=smtp.163.com
#spring.mail.host=smtp.exmail.qq.com
spring.mail.host=smtp.mailgun.org
#端口
spring.mail.port=465
#邮箱账号
spring.mail.username=service@mail.bbpk.com
#邮箱密码
spring.mail.password=bicai2019
#发件协议
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

demo/src/test/java/com/monkey/springboot/demo/DemoApplicationTests.java

package com.monkey.springboot.demo;import com.alibaba.fastjson.JSONObject;
import com.monkey.springboot.demo.utils.RSAUtils;
import org.apache.commons.codec.binary.Base64;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.HashMap;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {static String publicKey;static String privateKey;static {try {Map<String, Object> keyMap = RSAUtils.genKeyPair();publicKey = RSAUtils.getPublicKey(keyMap);privateKey = RSAUtils.getPrivateKey(keyMap);System.err.println("公钥: \n\r" + publicKey);System.err.println("私钥: \n\r" + privateKey);} catch (Exception e) {e.printStackTrace();}}@Testpublic void tests() throws Exception {//testJavaRsa();//testSign();test();//testJavaRsa();}static void testSign() throws Exception {System.err.println("私钥加密——公钥解密");String source = "32232";System.out.println("原文字:\r\n" + source);byte[] data = source.getBytes();byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);System.out.println("加密后:\r\n" + new String(encodedData));byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);String target = new String(decodedData);System.out.println("解密后: \r\n" + target);System.err.println("私钥签名——公钥验证签名");String sign = RSAUtils.sign(encodedData, privateKey);System.err.println("签名:\r" + sign);boolean status = RSAUtils.verify(encodedData, publicKey, sign);System.err.println("验证结果:\r" + status);}static void test() throws Exception {System.err.println("公钥加密——私钥解密");String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?";System.out.println("\r加密前文字:\r\n" + source);byte[] sourceBytes = source.getBytes("utf-8");byte[] data = sourceBytes;byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);System.out.println("加密后文字:\r\n" + new String(encodedData));System.out.println("----------------:base64处理:" + Base64.encodeBase64String(encodedData));byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);String target = new String(decodedData);System.out.println("解密后文字: \r\n" + target);}/** 测试自己封装java端加密和解密的方法*/static void testJavaRsa() {String PUBLICKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcd+0zTY9Gn94iqkQJTlxYnEnCeFsLkk0a7hoAvi2B74VzDVV3xH0ZO9RkXvo1SgCB+uzbEWdrgQkzTqyjfTtgOguu3OnkVxIMJF34ibchTY0LWHGxq1m2gLGuVVqrlu1LtdV0X7xo/5zc8Mr+46veWb86kSpqe6rOAm69WWo5GwIDAQAB";String PRIVATEKEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJx37TNNj0af3iKqRAlOXFicScJ4WwuSTRruGgC+LYHvhXMNVXfEfRk71GRe+jVKAIH67NsRZ2uBCTNOrKN9O2A6C67c6eRXEgwkXfiJtyFNjQtYcbGrWbaAsa5VWquW7Uu11XRfvGj/nNzwyv7jq95ZvzqRKmp7qs4Cbr1ZajkbAgMBAAECgYAHp349EkA+DjgJrhah9elilFKvZr/dcwy+koNHIgaL4rG+jRpvP3d3MowTVOocjUA1G5dWqCVNBwTyM5kSbl/nIxSCYwdUoDid4r0JbqkXkTTsIq3euHG8eiWr9rr3SDmwDojWoJEc4liVlfme8dQuMfgxe1QKq7wTrJwCKwbeMQJBAPwpknRPRK8W9hefbbtEu8mlbzUy+ER8Puq6dvS+lnWzJ8n2chJcHRYQFwWpjl4+SZuKeEcDmYmuQ7xuqEIayO0CQQCe2YeaxcU4uuDC45RAwCcMaNw1nDJuA+Gi47lXbroBXoeOiNZunViSZVUgDgrV/Ku6V54TaZIzZ21QFjf7mXEnAkEA7dZwMpAJonOvzfwrzbQ4wyrsx2q5zC68UT1qsdGJrJ48azutwC9tp7+pV0fj5nQtjS1/4Ms+aCQb84ET5rXIyQJAM0m45tgEHZT5DPO94kooUXFp6EVOYwcNyzILnZc6p0aGLhcwZPaYqmvdWEQwa3bxW3D+sPXdJou2V61U1f9s8QJALccvYwwWlCTq1iTmegYk9fOoc+isZKH+Z0YW70kFi94AYEO+utYwmXBEAqQ5VC/bywa1O71xdL4/RGCOSxBf2A==";Map map=new HashMap<String,String>();map.put("key","value");map.put("中文","汉字");String content = JSONObject.toJSONString(map);content = RSAUtils.encryptedDataOnJava(content, PUBLICKEY);System.out.println("加密数据:" + content);System.out.println("解密数据:" + RSAUtils.decryptDataOnJava(content, PRIVATEKEY));}static void testFrontEncrptAndAfterDecrypt() {String PRIVATEKEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIn2zWqU7K/2qm5pOpq5bp9R+3MTnStWTfJU9nC/Vo7UKH9dITPvrELCTK+qlqpx5Fes+l0GY7n6u4n4jyiw4ejsvkZYQ5ww477yLOn2FcoEGuZEwPgSCmfTST0OFUgQqn+/J11k9L92jEHyieE3qmhMkMt0UsVUSJwx/nZxo30ZAgMBAAECgYBD3YHigeuEC4R+14iaf8jo2j0kuGtB3Cxvnlez0otTqw1YyYkBsU49cLKkXvfKVEgM0Ow/QltgKvSBxCE31PrrDka5TygVMqqA/IM7NrDvjUcGLjyoeNmLA8660fWcDxUTlAGN5kxIvUATayVwKVflpWPWu0FPKsWrZustnEo+4QJBAMCmYsWqAKWYMVRXFP3/XGRfio8DV793TOckyBSN9eh8UhgoZyT3u7oeHmDJEwm4aNMHlg1Pcdc6tNsvi1FRCiUCQQC3VNzfF4xOtUgX7vWPL8YVljLuXmy12iVYmg6ofu9l31nwM9FLQ1TRFglvF5LWrIXTQb07PgGd5DJMAQWGsqLlAkAPE7Z9M73TN+L8b8hDzJ1leZi1cpSGdoa9PEKwYR/SrxAZtefEm+LEQSEtf+8OfrEtetWCeyo0pvKKiOEFXytFAkEAgynL/DC0yXsZYUYtmYvshHU5ayFTVagFICbYZeSrEo+BoUDxdI9vl0fU6A5NmBlGhaZ65G+waG5jLc1tTrlvoQJAXBEoPcBNAosiZHQfYBwHqU6mJ9/ZacJh3MtJzGGebfEwJgtln5b154iANqNWXpySBLvkK+Boq7FYRiD83pqmUg==";String data = "FBGU7sQfpSfCgB2hqFuIqkivEUHVRHD8JFdyxYeWqQHsTj9UEuVmvi28n1fOHRwW+3aZD3ttdzfUHWiXD2NErcX/CYs5BtSXT7RcJfWWcXvegq5BBDEAJCADWCRdYnblN+SLUC+ctDXcLw4xmjwAajowSzhCfY/lU3TdnJjO488=";System.out.println("解密数据:" + RSAUtils.decryptDataOnJava(data, PRIVATEKEY));}
}

https://github.com/qiangqiang666/demo相关推荐

  1. git 提交时报错 error: failed to push some refs to ‘https://github.com/xxx/demo.git 解决方法

    1. 前言 本文解决由于git 处于游离状态下不能提交代码的问题.文章由导致原因,解决方法和思考三个内容组成. 2. 问题复现 我们从远程仓库 clone 代码下来,进行需求开发,可能进行了以下步骤. ...

  2. Java分布式中文分词组件 - word分词(转自 https //github com/ysc/word)

    首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的.教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈-我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转 ...

  3. Java分布式中文分词组件 - word分词(转自:https://github.com/ysc/word)

    ###Java分布式中文分词组件 - word分词 ####word分词是一个Java实现的分布式的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义.能准确识别英文.数字,以 ...

  4. https://github.com/Wechat-Group/WxJava 使用记录

    GITHUB地址 https://github.com/Wechat-Group/WxJava 微信公众号开发 下载demo代码参考 https://gitee.com/binary/weixin-j ...

  5. 解决办法:error: failed to push some refs to 'https://github.com/xxxx.git'

    在github远程创建仓库后, 利用gitbash进行提交本地文件的时候出现如下错误: [root@foundation38 demo]# git push -u origin master User ...

  6. https://github.com/Trinea/android-open-project

    Android开源项目分类汇总 欢迎大家推荐好的Android开源项目,可直接Commit或在 收集&提交页 中告诉我,欢迎Star.Fork :) 微博:Trinea    主页:www.t ...

  7. android视频缓存框架 [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) 源码解析与评估

    文章目录 android视频缓存框架 [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) 源码解析与评估 引言 使用方 ...

  8. 我的GitHub:https://github.com/yuyufeng1994

    一些demo会放在我的GitHub仓库里,欢迎交流 地址:https://github.com/yuyufeng1994

  9. Android开源项目及库整理总结 字数10731 阅读2704 评论2 喜欢85 自己总结的Android开源项目及库。 github排名https://github.com/trending,

    Android开源项目及库整理总结 字数10731 阅读2704 评论2 喜欢85 自己总结的Android开源项目及库. github排名https://github.com/trending, g ...

  10. 一步一步指引你在Windows7上配置编译使用Caffe(https://github.com/fengbingchun/Caffe_Test)

    之前写过几篇关于Caffe源码在Windows764位上配置编译及使用过程,只是没有把整个工程放到网上,最近把整个工程整理清理了下,把它放到了GitHub上.下面对这个工程的使用作几点说明: 1.   ...

最新文章

  1. Anaconda中安装pytorch,并在pycharm中配置【win10】
  2. python状态机实现_如何实现Python状态机设计?
  3. React Native中常用ES6语法
  4. STM32F4 串口DMA
  5. 论文学习2-Incorporating Graph Attention Mechanism into Knowledge Graph Reasoning Based on Deep Reinforce
  6. Python globals 函数 - Python零基础入门教程
  7. [转]Best Practices for Speeding Up Your Web Site
  8. vue 跳转页面带对象_vue跳转页面的几种方法(推荐)
  9. python安装email模块,python 3.4.0电子邮件包安装:ImportError:没有名为'cStringIO'的模块...
  10. MFC API——》WM_NCHITTEST、OnNcHitTest (CPoint point) 点击鼠标时产生的消息
  11. FreeRTOS学习记录(安富莱FreeRTOS教程摘录)
  12. 三人表决器实验报告总结_三人表决器实验报告.doc
  13. unity3d 注册表 Regedit
  14. 惠普HP Designjet Z5200 PostScript 打印机驱动
  15. 利用css构建三角形(正三角,倒三角,左/右三角)
  16. 亚马逊ERP系统无货源采集上货软件
  17. 自学虚幻引擎图文笔记:颜色混合、法线强度调整及选择、归一化、点积、常量偏差比例、规范化等节点
  18. (11)点云数据处理学习——Colored point cloud registration(彩色点注册)
  19. 如何只更新datetime类型字段中的日期
  20. 23年PMP备考攻略+资料分享

热门文章

  1. Php货币计算怎么样才严谨,php怎样【货币问答】- php怎样所有答案 - 联合货币
  2. 如何拆分PDF文件?来看这两种方法
  3. 为防止程序员猝死,这家公司想出了一个好办法
  4. Unity 路径点弧线运动
  5. 地理信息系统软件学习:流域提取以及地图绘制(简单版)
  6. 帧中继网配置实例学习记录
  7. abap中方法file_open_dialog的使用
  8. 抖音播放量不到200,新手该如何自救?
  9. 360 无法显示网速
  10. CSDN——缩进两个字符