溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot中接口加密解密統(tǒng)一處理

發(fā)布時(shí)間:2020-03-25 14:58:09 來源:網(wǎng)絡(luò) 閱讀:3404 作者:nineteens 欄目:編程語言

  我們與客戶端的接口互動(dòng)的時(shí)候,為了更高的安全性,我們可能需要對(duì)接口加密(請求參數(shù)加密,服務(wù)端解密)、返回信息加密(服務(wù)端加密,客戶端解密),但是也不是所有的接口都這樣,有些接口可能不需要,我們可以使用注解來輕松達(dá)到此要求。

  將接口參數(shù)的加密解密和返回信息的加密解密分開,分別定義注解,利用Controller的ControllerAdvice來攔截所有的請求,在其中判斷是否需要加密解密,即可達(dá)到要求。

  使用方法:使用 DecryptRequest 和 EncryptResponse 注解即可,可以放在Controller的類和方法上,其中一個(gè)為false就不執(zhí)行了。像這樣:

  @RestController

  @RequestMapping("/test")

  //@DecryptRequest

  @EncryptResponse

  public class TestController {

  @Autowired

  @Qualifier("rrCrypto")

  private Crypto crypto;

  @DecryptRequest(false)

  @EncryptResponse(false)

  @RequestMapping(value = "/enc" , method = RequestMethod.POST)

  public String enc(@RequestBody String body){

  return crypto.encrypt(body);

  }

  }

  定義參數(shù)解密的注解,DecryptRequest。

  /**

  * 解密注解

  *

  *

  加了此注解的接口(true)將進(jìn)行數(shù)據(jù)解密操作(post的body) 可

  * 以放在類上,可以放在方法上

  * @author xiongshiyan

  */

  @Target({ElementType.METHOD , ElementType.TYPE})

  @Retention(RetentionPolicy.RUNTIME)

  @Documented

  public @interface DecryptRequest {

  /**

  * 是否對(duì)body進(jìn)行解密

  */

  boolean value() default true;

  }

  定義返回信息加密的注解,EncryptResponse。

  /**

  * 加密注解

  *

  *

  加了此注解的接口(true)將進(jìn)行數(shù)據(jù)加密操作

  * 可以放在類上,可以放在方法上

  * @author 熊詩言

  */

  @Target({ElementType.METHOD , ElementType.TYPE})

  @Retention(RetentionPolicy.RUNTIME)

  @Documented

  public @interface EncryptResponse {

  /**

  * 是否對(duì)結(jié)果加密

  */

  boolean value() default true;

  }

  這兩個(gè)注解可以放在類和方法上,遵循一樣的邏輯,即:類上的注解 && 方法上的注解,一方?jīng)]有即為true,都為false為false。邏輯主要在 NeedCrypto 中。

  /**

  * 判斷是否需要加解密

  * @author xiongshiyan at 2018/8/30 , contact me with email yanshixiong@126.com or phone 15208384257

  */

  class NeedCrypto {

  private NeedCrypto(){}

  /**

  * 是否需要對(duì)結(jié)果加密

  * 1.類上標(biāo)注或者方法上標(biāo)注,并且都為true

  * 2.有一個(gè)標(biāo)注為false就不需要加密

  */

  static boolean needEncrypt(MethodParameter returnType) {

  boolean encrypt = false;

  boolean classPresentAnno = returnType.getContainingClass().isAnnotationPresent(EncryptResponse.class);

  boolean methodPresentAnno = returnType.getMethod().isAnnotationPresent(EncryptResponse.class);

  if(classPresentAnno){

  //類上標(biāo)注的是否需要加密

  encrypt = returnType.getContainingClass().getAnnotation(EncryptResponse.class).value();

  //類不加密,所有都不加密

  if(!encrypt){

  return false;

  }

  }

  if(methodPresentAnno){

  //方法上標(biāo)注的是否需要加密

  encrypt = returnType.getMethod().getAnnotation(EncryptResponse.class).value();

  }

  return encrypt;

  }

  /**

  * 是否需要參數(shù)解密

  * 1.類上標(biāo)注或者方法上標(biāo)注,并且都為true

  * 2.有一個(gè)標(biāo)注為false就不需要解密

  */

  static boolean needDecrypt(MethodParameter parameter) {

  boolean encrypt = false;

  boolean classPresentAnno = parameter.getContainingClass().isAnnotationPresent(DecryptRequest.class);

  boolean methodPresentAnno = parameter.getMethod().isAnnotationPresent(DecryptRequest.class);

  if(classPresentAnno){

  //類上標(biāo)注的是否需要解密

  encrypt = parameter.getContainingClass().getAnnotation(DecryptRequest.class).value();

  //類不加密,所有都不加密

  if(!encrypt){

  return false;

  }

  }

  if(methodPresentAnno){

  //方法上標(biāo)注的是否需要解密

  encrypt = parameter.getMethod().getAnnotation(DecryptRequest.class).value();

  }

  return encrypt;

  }

  }

  然后定義ControllerAdvice,對(duì)于請求解密的,定義 DecryptRequestBodyAdvice ,實(shí)現(xiàn) RequestBodyAdvice 。

  /**

  * 請求數(shù)據(jù)接收處理類

  *

  * 對(duì)加了@Decrypt的方法的數(shù)據(jù)進(jìn)行解密操作

  *

  * 只對(duì) @RequestBody 參數(shù)有效

  * @author xiongshiyan

  */

  @ControllerAdvice

  @ConditionalOnProperty(prefix = "spring.crypto.request.decrypt", name = "enabled" , havingValue = "true", matchIfMissing = true)

  public class DecryptRequestBodyAdvice implements RequestBodyAdvice {

  @Value("${spring.crypto.request.decrypt.charset:UTF-8}")

  private String charset = "UTF-8";

  @Autowired

  @Qualifier("rrCrypto")

  private Crypto crypto;

  @Override

  public boolean supports(MethodParameter methodParameter, Type targetType,

  Class> converterType) {

  return true;

  }

  @Override

  public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,

  Type targetType, Class> converterType) {

  return body;

  }

  @Override

  public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,

  Class> converterType) throws IOException {

  if( NeedCrypto.needDecrypt(parameter) ){

  return new DecryptHttpInputMessage(inputMessage , charset , crypto);

  }

  return inputMessage;

  }

  @Override

  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,

  Class> converterType) {

  return body;

  }

  }無錫人流多少錢 http://www.bhnnk120.com/

  標(biāo)上注解 ConditionalOnProperty 表示只有條件為true的時(shí)候才開啟解密功能,一個(gè)配置即可打開或者關(guān)閉解密功能。真正的解密邏輯留給 DecryptHttpInputMessage , 它又委托給 Crypto。

  /**

  *

  * @author xiongshiyan

  */

  public class DecryptHttpInputMessage implements HttpInputMessage {

  private HttpInputMessage inputMessage;

  private String charset;

  private Crypto crypto;

  public DecryptHttpInputMessage(HttpInputMessage inputMessage, String charset , Crypto crypto) {

  this.inputMessage = inputMessage;

  this.charset = charset;

  this.crypto = crypto;

  }

  @Override

  public InputStream getBody() throws IOException {

  String content = IoUtil.read(inputMessage.getBody() , charset);

  String decryptBody = crypto.decrypt(content, charset);

  return new ByteArrayInputStream(decryptBody.getBytes(charset));

  }

  @Override

  public HttpHeaders getHeaders() {

  return inputMessage.getHeaders();

  }

  }

  對(duì)于返回值加密,定義 EncryptResponseBodyAdvice,實(shí)現(xiàn) ResponseBodyAdvice。

  /**

  * 請求響應(yīng)處理類

  *

  * 對(duì)加了@Encrypt的方法的數(shù)據(jù)進(jìn)行加密操作

  *

  * @author?

  *

  */

  @ControllerAdvice

  @ConditionalOnProperty(prefix = "spring.crypto.response.encrypt", name = "enabled" , havingValue = "true", matchIfMissing = true)

  public class EncryptResponseBodyAdvice implements ResponseBodyAdvice


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI