在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SpringBoot接口加密解密,新姿勢!

jf_ro2CN3Fa ? 來源:芋道源碼 ? 作者:芋道源碼 ? 2022-11-29 11:13 ? 次閱讀


1. 介紹

在我們日常的Java開發中,免不了和其他系統的業務交互,或者微服務之間的接口調用

如果我們想保證數據傳輸的安全,對接口出參加密,入參解密。

但是不想寫重復代碼,我們可以提供一個通用starter,提供通用加密解密功能

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

2. 前置知識

2.1 hutool-crypto加密解密工具

hutool-crypto提供了很多加密解密工具,包括對稱加密,非對稱加密,摘要加密等等,這不做詳細介紹。

2.2 request流只能讀取一次的問題

2.2.1 問題:

在接口調用鏈中,request的請求流只能調用一次,處理之后,如果之后還需要用到請求流獲取數據,就會發現數據為空。

比如使用了filter或者aop在接口處理之前,獲取了request中的數據,對參數進行了校驗,那么之后就不能在獲取request請求流了

2.2.2 解決辦法

繼承HttpServletRequestWrapper,將請求中的流copy一份,復寫getInputStream和getReader方法供外部使用。每次調用后的getInputStream方法都是從復制出來的二進制數組中進行獲取,這個二進制數組在對象存在期間一致存在。

使用Filter過濾器,在一開始,替換request為自己定義的可以多次讀取流的request。

這樣就實現了流的重復獲取

InputStreamHttpServletRequestWrapper

packagexyz.hlh.cryptotest.utils;

importorg.apache.commons.io.IOUtils;

importjavax.servlet.ReadListener;
importjavax.servlet.ServletInputStream;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletRequestWrapper;
importjava.io.BufferedReader;
importjava.io.ByteArrayInputStream;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.io.InputStreamReader;

/**
*請求流支持多次獲取
*/
publicclassInputStreamHttpServletRequestWrapperextendsHttpServletRequestWrapper{

/**
*用于緩存輸入流
*/
privateByteArrayOutputStreamcachedBytes;

publicInputStreamHttpServletRequestWrapper(HttpServletRequestrequest){
super(request);
}

@Override
publicServletInputStreamgetInputStream()throwsIOException{
if(cachedBytes==null){
//首次獲取流時,將流放入緩存輸入流中
cacheInputStream();
}

//從緩存輸入流中獲取流并返回
returnnewCachedServletInputStream(cachedBytes.toByteArray());
}

@Override
publicBufferedReadergetReader()throwsIOException{
returnnewBufferedReader(newInputStreamReader(getInputStream()));
}

/**
*首次獲取流時,將流放入緩存輸入流中
*/
privatevoidcacheInputStream()throwsIOException{
//緩存輸入流以便多次讀取。為了方便, 我使用 org.apache.commons IOUtils
cachedBytes=newByteArrayOutputStream();
IOUtils.copy(super.getInputStream(),cachedBytes);
}

/**
*讀取緩存的請求正文的輸入流
*

*用于根據緩存輸入流創建一個可返回的 */ publicstaticclassCachedServletInputStreamextendsServletInputStream{ privatefinalByteArrayInputStreaminput; publicCachedServletInputStream(byte[]buf){ //從緩存的請求正文創建一個新的輸入流 input=newByteArrayInputStream(buf); } @Override publicbooleanisFinished(){ returnfalse; } @Override publicbooleanisReady(){ returnfalse; } @Override publicvoidsetReadListener(ReadListenerlistener){ } @Override publicintread()throwsIOException{ returninput.read(); } } }

HttpServletRequestInputStreamFilter

packagexyz.hlh.cryptotest.filter;

importorg.springframework.core.annotation.Order;
importorg.springframework.stereotype.Component;
importxyz.hlh.cryptotest.utils.InputStreamHttpServletRequestWrapper;

importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjava.io.IOException;

importstaticorg.springframework.core.Ordered.HIGHEST_PRECEDENCE;

/**
*@authorHLH
*@description:
*請求流轉換為多次讀取的請求流過濾器
*@email17703595860@163.com
*@date:Createdin2022/2/49:58
*/
@Component
@Order(HIGHEST_PRECEDENCE+1)//優先級最高
publicclassHttpServletRequestInputStreamFilterimplementsFilter{

@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

//轉換為可以多次獲取流的request
HttpServletRequesthttpServletRequest=(HttpServletRequest)request;
InputStreamHttpServletRequestWrapperinputStreamHttpServletRequestWrapper=newInputStreamHttpServletRequestWrapper(httpServletRequest);

//放行
chain.doFilter(inputStreamHttpServletRequestWrapper,response);
}
}

2.3 SpringBoot的參數校驗validation

為了減少接口中,業務代碼之前的大量冗余的參數校驗代碼

SpringBoot-validation提供了優雅的參數校驗,入參都是實體類,在實體類字段上加上對應注解,就可以在進入方法之前,進行參數校驗,如果參數錯誤,會拋出錯誤BindException,是不會進入方法的。

這種方法,必須要求在接口參數上加注解@Validated或者是@Valid

但是很多清空下,我們希望在代碼中調用某個實體類的校驗功能,所以需要如下工具類

ParamException

packagexyz.hlh.cryptotest.exception;

importlombok.Getter;

importjava.util.List;

/**
*@authorHLH
*@description自定義參數異常
*@email17703595860@163.com
*@dateCreatedin2021/8/10下午10:56
*/
@Getter
publicclassParamExceptionextendsException{

privatefinalListfieldList;
privatefinalListmsgList;

publicParamException(ListfieldList,ListmsgList){
this.fieldList=fieldList;
this.msgList=msgList;
}
}

ValidationUtils

packagexyz.hlh.cryptotest.utils;

importxyz.hlh.cryptotest.exception.CustomizeException;
importxyz.hlh.cryptotest.exception.ParamException;

importjavax.validation.ConstraintViolation;
importjavax.validation.Validation;
importjavax.validation.Validator;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.Set;

/**
*@authorHLH
*@description驗證工具類
*@email17703595860@163.com
*@dateCreatedin2021/8/10下午10:56
*/
publicclassValidationUtils{

privatestaticfinalValidatorVALIDATOR=Validation.buildDefaultValidatorFactory().getValidator();

/**
*驗證數據
*@paramobject數據
*/
publicstaticvoidvalidate(Objectobject)throwsCustomizeException{

Set>validate=VALIDATOR.validate(object);

//驗證結果異常
throwParamException(validate);
}

/**
*驗證數據(分組)
*@paramobject數據
*@paramgroups所在組
*/
publicstaticvoidvalidate(Objectobject,Class...groups)throwsCustomizeException{

Set>validate=VALIDATOR.validate(object,groups);

//驗證結果異常
throwParamException(validate);
}

/**
*驗證數據中的某個字段(分組)
*@paramobject數據
*@parampropertyName字段名稱
*/
publicstaticvoidvalidate(Objectobject,StringpropertyName)throwsCustomizeException{
Set>validate=VALIDATOR.validateProperty(object,propertyName);

//驗證結果異常
throwParamException(validate);

}

/**
*驗證數據中的某個字段(分組)
*@paramobject數據
*@parampropertyName字段名稱
*@paramgroups所在組
*/
publicstaticvoidvalidate(Objectobject,StringpropertyName,Class...groups)throwsCustomizeException{

Set>validate=VALIDATOR.validateProperty(object,propertyName,groups);

//驗證結果異常
throwParamException(validate);

}

/**
*驗證結果異常
*@paramvalidate驗證結果
*/
privatestaticvoidthrowParamException(Set>validate)throwsCustomizeException{
if(validate.size()>0){
ListfieldList=newLinkedList<>();
ListmsgList=newLinkedList<>();
for(ConstraintViolationnext:validate){
fieldList.add(next.getPropertyPath().toString());
msgList.add(next.getMessage());
}

thrownewParamException(fieldList,msgList);
}
}

}

		

2.4 自定義starter

自定義starter步驟

  • 創建工廠,編寫功能代碼

  • 聲明自動配置類,把需要對外提供的對象創建好,通過配置類統一向外暴露

  • 在resource目錄下準備一個名為spring/spring.factories的文件,以org.springframework.boot.autoconfigure.EnableAutoConfiguration為key,自動配置類為value列表,進行注冊

2.5 RequestBodyAdvice和ResponseBodyAdvice

  • RequestBodyAdvice是對請求的json串進行處理, 一般使用環境是處理接口參數的自動解密

  • ResponseBodyAdvice是對請求相應的jsoin傳進行處理,一般用于相應結果的加密

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

3. 功能介紹

接口相應數據的時候,返回的是加密之后的數據 接口入參的時候,接收的是解密之后的數據,但是在進入接口之前,會自動解密,取得對應的數據

4. 功能細節

加密解密使用對稱加密的AES算法,使用hutool-crypto模塊進行實現

所有的實體類提取一個公共父類,包含屬性時間戳,用于加密數據返回之后的實效性,如果超過60分鐘,那么其他接口將不進行處理。

如果接口加了加密注解EncryptionAnnotation,并且返回統一的json數據Result類,則自動對數據進行加密。如果是繼承了統一父類RequestBase的數據,自動注入時間戳,確保數據的時效性

如果接口加了解密注解DecryptionAnnotation,并且參數使用RequestBody注解標注,傳入json使用統一格式RequestData類,并且內容是繼承了包含時間長的父類RequestBase,則自動解密,并且轉為對應的數據類型

功能提供Springboot的starter,實現開箱即用

5. 代碼實現

https://gitee.com/springboot-hlh/spring-boot-csdn/tree/master/09-spring-boot-interface-crypto

5.1 項目結構

28f5d220-6f8b-11ed-8abf-dac502259ad0.png

5.2 crypto-common

5.2.1 結構

29035a26-6f8b-11ed-8abf-dac502259ad0.png

5.3 crypto-spring-boot-starter

5.3.1 接口

291bc674-6f8b-11ed-8abf-dac502259ad0.png

5.3.2 重要代碼

crypto.properties AES需要的參數配置

#模式cn.hutool.crypto.Mode
crypto.mode=CTS
#補碼方式cn.hutool.crypto.Mode
crypto.padding=PKCS5Padding
#秘鑰
crypto.key=testkey123456789
#鹽
crypto.iv=testiv1234567890

spring.factories 自動配置文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
xyz.hlh.crypto.config.AppConfig

CryptConfig AES需要的配置參數

packagexyz.hlh.crypto.config;

importcn.hutool.crypto.Mode;
importcn.hutool.crypto.Padding;
importlombok.Data;
importlombok.EqualsAndHashCode;
importlombok.Getter;
importorg.springframework.boot.context.properties.ConfigurationProperties;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.context.annotation.PropertySource;

importjava.io.Serializable;

/**
*@authorHLH
*@description:AES需要的配置參數
*@email17703595860@163.com
*@date:Createdin2022/2/413:16
*/
@Configuration
@ConfigurationProperties(prefix="crypto")
@PropertySource("classpath:crypto.properties")
@Data
@EqualsAndHashCode
@Getter
publicclassCryptConfigimplementsSerializable{

privateModemode;
privatePaddingpadding;
privateStringkey;
privateStringiv;

}

AppConfig 自動配置類

packagexyz.hlh.crypto.config;

importcn.hutool.crypto.symmetric.AES;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;

importjavax.annotation.Resource;
importjava.nio.charset.StandardCharsets;

/**
*@authorHLH
*@description:自動配置類
*@email17703595860@163.com
*@date:Createdin2022/2/413:12
*/
@Configuration
publicclassAppConfig{

@Resource
privateCryptConfigcryptConfig;

@Bean
publicAESaes(){
returnnewAES(cryptConfig.getMode(),cryptConfig.getPadding(),cryptConfig.getKey().getBytes(StandardCharsets.UTF_8),cryptConfig.getIv().getBytes(StandardCharsets.UTF_8));
}

}

DecryptRequestBodyAdvice 請求自動解密

packagexyz.hlh.crypto.advice;

importcom.fasterxml.jackson.databind.ObjectMapper;
importlombok.SneakyThrows;
importorg.apache.commons.lang3.StringUtils;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.core.MethodParameter;
importorg.springframework.http.HttpInputMessage;
importorg.springframework.http.converter.HttpMessageConverter;
importorg.springframework.web.bind.annotation.ControllerAdvice;
importorg.springframework.web.context.request.RequestAttributes;
importorg.springframework.web.context.request.RequestContextHolder;
importorg.springframework.web.context.request.ServletRequestAttributes;
importorg.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
importxyz.hlh.crypto.annotation.DecryptionAnnotation;
importxyz.hlh.crypto.common.exception.ParamException;
importxyz.hlh.crypto.constant.CryptoConstant;
importxyz.hlh.crypto.entity.RequestBase;
importxyz.hlh.crypto.entity.RequestData;
importxyz.hlh.crypto.util.AESUtil;

importjavax.servlet.ServletInputStream;
importjavax.servlet.http.HttpServletRequest;
importjava.io.IOException;
importjava.lang.reflect.Type;

/**
*@authorHLH
*@description:requestBody自動解密
*@email17703595860@163.com
*@date:Createdin2022/2/415:12
*/
@ControllerAdvice
publicclassDecryptRequestBodyAdviceimplementsRequestBodyAdvice{

@Autowired
privateObjectMapperobjectMapper;

/**
*方法上有DecryptionAnnotation注解的,進入此攔截器
*@parammethodParameter方法參數對象
*@paramtargetType參數的類型
*@paramconverterType消息轉換器
*@returntrue,進入,false,跳過
*/
@Override
publicbooleansupports(MethodParametermethodParameter,TypetargetType,Class>converterType){
returnmethodParameter.hasMethodAnnotation(DecryptionAnnotation.class);
}

@Override
publicHttpInputMessagebeforeBodyRead(HttpInputMessageinputMessage,MethodParameterparameter,TypetargetType,Class>converterType)throwsIOException{
returninputMessage;
}

/**
*轉換之后,執行此方法,解密,賦值
*@parambodyspring解析完的參數
*@paraminputMessage輸入參數
*@paramparameter參數對象
*@paramtargetType參數類型
*@paramconverterType消息轉換類型
*@return真實的參數
*/
@SneakyThrows
@Override
publicObjectafterBodyRead(Objectbody,HttpInputMessageinputMessage,MethodParameterparameter,TypetargetType,Class>converterType){

//獲取request
RequestAttributesrequestAttributes=RequestContextHolder.getRequestAttributes();
ServletRequestAttributesservletRequestAttributes=(ServletRequestAttributes)requestAttributes;
if(servletRequestAttributes==null){
thrownewParamException("request錯誤");
}

HttpServletRequestrequest=servletRequestAttributes.getRequest();

//獲取數據
ServletInputStreaminputStream=request.getInputStream();
RequestDatarequestData=objectMapper.readValue(inputStream,RequestData.class);

if(requestData==null||StringUtils.isBlank(requestData.getText())){
thrownewParamException("參數錯誤");
}

//獲取加密的數據
Stringtext=requestData.getText();

//放入解密之前的數據
request.setAttribute(CryptoConstant.INPUT_ORIGINAL_DATA,text);

//解密
StringdecryptText=null;
try{
decryptText=AESUtil.decrypt(text);
}catch(Exceptione){
thrownewParamException("解密失敗");
}

if(StringUtils.isBlank(decryptText)){
thrownewParamException("解密失敗");
}

//放入解密之后的數據
request.setAttribute(CryptoConstant.INPUT_DECRYPT_DATA,decryptText);

//獲取結果
Objectresult=objectMapper.readValue(decryptText,body.getClass());

//強制所有實體類必須繼承RequestBase類,設置時間戳
if(resultinstanceofRequestBase){
//獲取時間戳
LongcurrentTimeMillis=((RequestBase)result).getCurrentTimeMillis();
//有效期60秒
longeffective=60*1000;

//時間差
longexpire=System.currentTimeMillis()-currentTimeMillis;

//是否在有效期內
if(Math.abs(expire)>effective){
thrownewParamException("時間戳不合法");
}

//返回解密之后的數據
returnresult;
}else{
thrownewParamException(String.format("請求參數類型:%s 未繼承:%s",result.getClass().getName(),RequestBase.class.getName()));
}
}

/**
*如果body為空,轉為空對象
*@parambodyspring解析完的參數
*@paraminputMessage輸入參數
*@paramparameter參數對象
*@paramtargetType參數類型
*@paramconverterType消息轉換類型
*@return真實的參數
*/
@SneakyThrows
@Override
publicObjecthandleEmptyBody(Objectbody,HttpInputMessageinputMessage,MethodParameterparameter,TypetargetType,Class>converterType){
StringtypeName=targetType.getTypeName();
ClassbodyClass=Class.forName(typeName);
returnbodyClass.newInstance();
}
}

EncryptResponseBodyAdvice 相應自動加密

packagexyz.hlh.crypto.advice;

importcn.hutool.json.JSONUtil;
importcom.fasterxml.jackson.databind.ObjectMapper;
importlombok.SneakyThrows;
importorg.apache.commons.lang3.StringUtils;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.core.MethodParameter;
importorg.springframework.http.MediaType;
importorg.springframework.http.ResponseEntity;
importorg.springframework.http.converter.HttpMessageConverter;
importorg.springframework.http.server.ServerHttpRequest;
importorg.springframework.http.server.ServerHttpResponse;
importorg.springframework.web.bind.annotation.ControllerAdvice;
importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
importsun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
importxyz.hlh.crypto.annotation.EncryptionAnnotation;
importxyz.hlh.crypto.common.entity.Result;
importxyz.hlh.crypto.common.exception.CryptoException;
importxyz.hlh.crypto.entity.RequestBase;
importxyz.hlh.crypto.util.AESUtil;

importjava.lang.reflect.Type;

/**
*@authorHLH
*@description:
*@email17703595860@163.com
*@date:Createdin2022/2/415:12
*/
@ControllerAdvice
publicclassEncryptResponseBodyAdviceimplementsResponseBodyAdvice<Result>{

@Autowired
privateObjectMapperobjectMapper;

@Override
publicbooleansupports(MethodParameterreturnType,Class>converterType){
ParameterizedTypeImplgenericParameterType=(ParameterizedTypeImpl)returnType.getGenericParameterType();

//如果直接是Result,則返回
if(genericParameterType.getRawType()==Result.class&&returnType.hasMethodAnnotation(EncryptionAnnotation.class)){
returntrue;
}

if(genericParameterType.getRawType()!=ResponseEntity.class){
returnfalse;
}

//如果是ResponseEntity
for(Typetype:genericParameterType.getActualTypeArguments()){
if(((ParameterizedTypeImpl)type).getRawType()==Result.class&&returnType.hasMethodAnnotation(EncryptionAnnotation.class)){
returntrue;
}
}

returnfalse;
}

@SneakyThrows
@Override
publicResultbeforeBodyWrite(Resultbody,MethodParameterreturnType,MediaTypeselectedContentType,Class>selectedConverterType,ServerHttpRequestrequest,ServerHttpResponseresponse){

//加密
Objectdata=body.getData();

//如果data為空,直接返回
if(data==null){
returnbody;
}

//如果是實體,并且繼承了Request,則放入時間戳
if(datainstanceofRequestBase){
((RequestBase)data).setCurrentTimeMillis(System.currentTimeMillis());
}

StringdataText=JSONUtil.toJsonStr(data);

//如果data為空,直接返回
if(StringUtils.isBlank(dataText)){
returnbody;
}

//如果位數小于16,報錯
if(dataText.length()16){
thrownewCryptoException("加密失敗,數據小于16位");
}

StringencryptText=AESUtil.encryptHex(dataText);

returnResult.builder()
.status(body.getStatus())
.data(encryptText)
.message(body.getMessage())
.build();
}
}

5.4 crypto-test

5.4.1 結構

292e5bc2-6f8b-11ed-8abf-dac502259ad0.png

5.4.2 重要代碼

application.yml 配置文件

spring:
mvc:
format:
date-time:yyyy-MM-ddHHss
date:yyyy-MM-dd
#日期格式化
jackson:
date-format:yyyy-MM-ddHHss

Teacher 實體類

packagexyz.hlh.crypto.entity;

importlombok.AllArgsConstructor;
importlombok.Data;
importlombok.EqualsAndHashCode;
importlombok.NoArgsConstructor;
importorg.hibernate.validator.constraints.Range;

importjavax.validation.constraints.NotBlank;
importjavax.validation.constraints.NotNull;
importjava.io.Serializable;
importjava.util.Date;

/**
*@authorHLH
*@description:Teacher實體類,使用SpringBoot的validation校驗
*@email17703595860@163.com
*@date:Createdin2022/2/410:21
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper=true)
publicclassTeacherextendsRequestBaseimplementsSerializable{

@NotBlank(message="姓名不能為空")
privateStringname;
@NotNull(message="年齡不能為空")
@Range(min=0,max=150,message="年齡不合法")
privateIntegerage;
@NotNull(message="生日不能為空")
privateDatebirthday;

}

TestController 測試Controller

packagexyz.hlh.crypto.controller;

importorg.springframework.http.ResponseEntity;
importorg.springframework.validation.annotation.Validated;
importorg.springframework.web.bind.annotation.PostMapping;
importorg.springframework.web.bind.annotation.RequestBody;
importorg.springframework.web.bind.annotation.RestController;
importxyz.hlh.crypto.annotation.DecryptionAnnotation;
importxyz.hlh.crypto.annotation.EncryptionAnnotation;
importxyz.hlh.crypto.common.entity.Result;
importxyz.hlh.crypto.common.entity.ResultBuilder;
importxyz.hlh.crypto.entity.Teacher;

/**
*@authorHLH
*@description:測試Controller
*@email17703595860@163.com
*@date:Createdin2022/2/49:16
*/
@RestController
publicclassTestControllerimplementsResultBuilder{

/**
*直接返回對象,不加密
*@paramteacherTeacher對象
*@return不加密的對象
*/
@PostMapping("/get")
publicResponseEntity>get(@Validated@RequestBodyTeacherteacher){
returnsuccess(teacher);
}

/**
*返回加密后的數據
*@paramteacherTeacher對象
*@return返回加密后的數據ResponseBody格式
*/
@PostMapping("/encrypt")
@EncryptionAnnotation
publicResponseEntity>encrypt(@Validated@RequestBodyTeacherteacher){
returnsuccess(teacher);
}

/**
*返回加密后的數據
*@paramteacherTeacher對象
*@return返回加密后的數據Result格式
*/
@PostMapping("/encrypt1")
@EncryptionAnnotation
publicResultencrypt1(@Validated@RequestBodyTeacherteacher){
returnsuccess(teacher).getBody();
}

/**
*返回解密后的數據
*@paramteacherTeacher對象
*@return返回解密后的數據
*/
@PostMapping("/decrypt")
@DecryptionAnnotation
publicResponseEntity>decrypt(@Validated@RequestBodyTeacherteacher){
returnsuccess(teacher);
}

}


審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    20

    文章

    2987

    瀏覽量

    107247
  • 管理系統
    +關注

    關注

    1

    文章

    2751

    瀏覽量

    36840
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14928
  • SpringBoot
    +關注

    關注

    0

    文章

    175

    瀏覽量

    335

原文標題:SpringBoot 接口加密解密,新姿勢!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    GLAD:利用全息圖實現加密解密

    概述 全息圖能夠通過兩束相干光相干疊加獲得。用其中一束光照射生成的全息圖就可以得到另一束相干光,這樣全息圖就可以用作加密/解密的裝置了。 系統描述 在本例中一個復雜的隨機圖樣作為參考光源,用來恢復
    發表于 06-13 08:42

    如何在MBDT中使用S32k344進行加密

    我想加密解密通過 CAN 總線發送的數據,為此我想使用 S32k344 中的 HSE 模塊在 MBDT 1.5 中進行對稱加密-解密,但工具箱中沒有可用的塊。那我該怎么做呢。請分享與
    發表于 03-25 07:21

    華企盾:保護設計成果,一文教你如何給CAD圖紙加密

    保護措施,助您輕松守護設計安全。 方法一:部署華企盾DSC數據防泄密系統: 透明加密技術:該技術讓加密過程對用戶無感,保持原有的工作流程和習慣不變。 自動加密解密:在圖紙的創建、編輯和
    的頭像 發表于 03-10 15:01 ?268次閱讀

    Boot0通過10k電阻接地,Boot1作為輸入使用被配置成外部中斷,為什么會導致單片機加密無法運行,且無法解密

    Boot0通過10k電阻接地,Boot1作為輸入使用被配置成外部中斷,現在存在的問題是可能會導致單片機加密無法運行,且無法解密,RDP顯示為FF,這是怎么導致的?
    發表于 03-10 07:26

    年前再補課!國產 ARM 平臺上演加密解密秀教學!

    一、產品簡介TL3568-PlusTEB人工智能實驗箱國產高性能處理器64位4核低功耗2.0GHz超高主頻1T超高算力NPU兼容鴻蒙等國產操作系統二、實驗目的1、了解常見的加密方法;2、加密解密
    的頭像 發表于 01-23 11:30 ?435次閱讀
    年前再補課!國產 ARM 平臺上演<b class='flag-5'>加密</b><b class='flag-5'>解密</b>秀教學!

    加密芯片的一種破解方法和對應加密方案改進設計

    ? ? ? 本文用實例描述了如何破 解、解密使用邏輯加密芯片保護的STM32方案,包括如果固定ID和固定隨機數。后面提出了加強加密方案的一些小技巧,并提出為何使用可編程加密芯片可提高
    發表于 12-30 14:04 ?1次下載

    STM32配合可編程加密芯片SMEC88ST的防抄板加密方案設計

    SEMC88ST與STM32配的的各種加密功能說明,具體可參見SMEC88ST SDK開發包。 注: ①STM32與SMEC88ST間的I2C協議指令接口規則開發者自定義。 ②上述加解密密鑰均為對稱DES或
    發表于 12-27 13:03

    EMMC數據加密技術與應用

    特點,但同時也面臨著數據泄露的風險。 數據加密技術概述 數據加密技術是保護數據不被未授權訪問的有效手段。它通過將明文數據轉換成密文,確保只有擁有正確密鑰的用戶才能解密并訪問原始數據。 對稱加密
    的頭像 發表于 12-25 09:51 ?1139次閱讀

    【RA-Eco-RA4E2-64PIN-V1.0開發板試用】RA4E2使用之AES128加密解密

    現在的電子設備中,通訊報文的收發都需要進行加密解密操作,不能明文發送,因為明文容易被黑客破解出協議報文,進而改動協議數據,以偽指令報文的方式進行發送,這樣會造成非常嚴重的安全隱患,尤其是在生
    發表于 12-23 17:29

    淺談加密芯片的一種破解方法和對應加密方案改進設計

    Key計算臨時過程秘鑰Key’,再使用臨時過程秘鑰Key’對數據做加解密和密文通訊,這樣來做到每一顆芯片、每一次通訊的加密數據都是不一樣,防止數據在通訊線路上被破解。 如上圖,主MCU函數FUNC
    發表于 12-20 15:31

    淺談加密芯片的一種破解方法和加密方案改進設計

    Key計算臨時過程秘鑰Key’,再使用臨時過程秘鑰Key’對數據做加解密和密文通訊,這樣來做到每一顆芯片、每一次通訊的加密數據都是不一樣,防止數據在通訊線路上被破解。 如上圖,主MCU函數FUNC
    發表于 12-20 15:10

    aes加密的常見錯誤及解決方案

    的歸納以及相應的解決方案: 常見錯誤 編碼問題 : 在將字節數組轉換成字符串時,如果使用了不同的編碼格式,可能會導致解密后的數據出現亂碼。 密鑰長度問題 : AES算法支持128位、192位和256位三種密鑰長度。如果加密解密
    的頭像 發表于 11-14 15:13 ?3901次閱讀

    socket 加密通信的實現方式

    握手過程協商加密算法、生成會話密鑰。 數據傳輸: 使用協商的加密算法和會話密鑰對數據進行加密解密。 結束握手: 通信結
    的頭像 發表于 11-12 14:18 ?1338次閱讀

    安卓APP開發中,如何使用加密芯片?

    加密芯片是一種專門設計用于保護信息安全的硬件設備,它通過內置的加密算法對數據進行加密解密,以防止敏感數據被竊取或篡改。如下圖HD-RK3568-IOT工控板,搭載ATSHA204A
    的頭像 發表于 10-31 17:43 ?921次閱讀
    安卓APP開發中,如何使用<b class='flag-5'>加密</b>芯片?

    用 AI 解鎖技術調研的新姿勢

    1. 前言 在日常開發中,為了保證技術方案的質量,一般會在撰寫前進行調研。如果先前沒有相關領域的知識儲備,筆者的調研方式一般是先通過搜索引擎進行關鍵字查詢,然后再基于搜索的結果進行發散。這樣調研的結果受關鍵字抽象程度和搜索引擎排名影響較大,可能會存在偏差導致調研不充分。剛好大模型風靡有一段時間了,就想如果AI能自動檢索資料并進行內容總結,豈不美哉。避免重復造輪子,先在網上檢索了一下,發現剛好有一個工具“ ST
    的頭像 發表于 08-05 13:44 ?385次閱讀
    用 AI 解鎖技術調研的<b class='flag-5'>新姿勢</b>
    主站蜘蛛池模板: 有一婷婷色| 亚洲黄色官网 | 亚洲三级电影在线播放 | 日日天天干 | 久久瑟 | 女人张开腿给男人桶爽免费 | 四虎影院在线观看免费 | 性色成人网 | 日韩一级在线观看 | 色香蕉在线观看 | 你懂的网站在线 | 无遮挡很爽很污很黄很色的网站 | www网站在线观看 | 国产黄色视屏 | 成年1314在线观看 | 乱肉情欲杂乱小说 | 老色歌uuu26 老湿成人影院 | 好骚综合在线 | 国产成人1024精品免费 | 91亚色视频| 欧美色图亚洲自拍 | 亚洲一区二区三区高清 | 国模大尺度人体一区 | 日本三级强在线观看 | 亚洲视频天天射 | 天天躁夜夜躁狠狠躁2021a | 天天操天天干天天拍 | 555成人免费影院 | 国产情侣出租屋露脸实拍 | 亚洲网站大全 | 影视精品网站入口 | 夜夜操夜夜骑 | 国产精品久久久久影视不卡 | 午夜美女影院 | 美女被免费网站91色 | 亚洲人成电影在线 | 国产婷婷色一区二区三区深爱网 | 艹逼视频免费观看 | 免费国产zzzwww色 | 男女吃奶一进一出动态图 | 国产人成午夜免费看 |