Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the encryption and decryption of Spring Boot interface parameters

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "how to realize the encryption and decryption of Spring Boot interface parameters". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "how to achieve Spring Boot interface parameters encryption and decryption" bar!

Encryption and decryption itself is not a difficult task, the question is when to deal with it? It is also an approach to define a filter to intercept the request and response separately for processing, which is rough but flexible because you can get first-hand request parameters and response data. However, SpringMVC provides us with ResponseBodyAdvice and RequestBodyAdvice, which can be used to preprocess requests and responses, which is very convenient.

So today's article has two purposes:

Sharing parameters / response encryption and decryption ideas.

Share the usage of ResponseBodyAdvice and RequestBodyAdvice.

All right, then let's cut the crap. Let's take a look.

1. Develop encryption and decryption starter

In order to make the tool we developed more generic and to review the custom Spring Boot Starter, here we will make the tool into a stater, which can be referenced directly in the Spring Boot project later.

First, let's create a Spring Boot project and introduce spring-boot-starter-web dependencies:

Org.springframework.boot spring-boot-starter-web provided 2.4.3

Because our tool is developed for the Web project, it must be used in the Web environment in the future, so the scope is set to provided when adding dependencies here.

After the dependency is added, we first define an encryption tool class as an alternative. There are a variety of options for encryption: symmetric encryption, asymmetric encryption, in which symmetric encryption can use different algorithms such as AES, DES, 3DES and so on. Here we use Cipher of Java to implement symmetric encryption, using AES algorithm:

Public class AESUtils {private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding"; / / get cipher private static Cipher getCipher (byte [] key, int model) throws Exception {SecretKeySpec secretKeySpec = new SecretKeySpec (key, "AES"); Cipher cipher = Cipher.getInstance (AES_ALGORITHM); cipher.init (model, secretKeySpec); return cipher } / / AES encryption public static String encrypt (byte [] data, byte [] key) throws Exception {Cipher cipher = getCipher (key, Cipher.ENCRYPT_MODE); return Base64.getEncoder () .encodeToString (cipher.doFinal (data));} / / AES decryption public static byte [] decrypt (byte [] data, byte [] key) throws Exception {Cipher cipher = getCipher (key, Cipher.DECRYPT_MODE) Return cipher.doFinal (Base64.getDecoder () .decode (data));}

This tool class is relatively simple and does not require much explanation. It should be noted that the encrypted data may not be readable, so we generally need to encode the encrypted data using the Base64 algorithm to obtain readable strings. In other words, the return value of the above AES encryption method is a Base64-encoded string, and the parameter of the AES decryption method is also a Base64-encoded string, which is decoded and then decrypted.

Next, let's package a response tool class as a backup, which is already well known if you often watch Song GE's video:

Public class RespBean {private Integer status; private String msg; private Object obj; public static RespBean build () {return new RespBean ();} public static RespBean ok (String msg) {return new RespBean (200, msg, null);} public static RespBean ok (String msg, Object obj) {return new RespBean (200, msg, obj) } public static RespBean error (String msg) {return new RespBean (500, msg, null);} public static RespBean error (String msg, Object obj) {return new RespBean (500, msg, obj);} private RespBean () {} private RespBean (Integer status, String msg, Object obj) {this.status = status; this.msg = msg; this.obj = obj } public Integer getStatus () {return status;} public RespBean setStatus (Integer status) {this.status = status; return this;} public String getMsg () {return msg;} public RespBean setMsg (String msg) {this.msg = msg; return this;} public Object getObj () {return obj } public RespBean setObj (Object obj) {this.obj = obj; return this;}}

Next we define two annotations @ Decrypt and @ Encrypt:

Retention (RetentionPolicy.RUNTIME) @ Target ({ElementType.METHOD,ElementType.PARAMETER}) public @ interface Decrypt {} @ Retention (RetentionPolicy.RUNTIME) @ Target (ElementType.METHOD) public @ interface Encrypt {}

These two annotations are two tags. In the process of later use, the data of which interface method adds @ Encrypt annotation will be encrypted and returned, and which interface / parameter will be decrypted. This definition is also relatively simple, there is nothing to say, it is important to note that @ Decrypt has one more use scenario than @ Encrypt, that is, @ Decrypt can be used on parameters.

Considering that the user may configure the encrypted key himself, let's define an EncryptProperties class to read the user-configured key:

ConfigurationProperties (prefix = "spring.encrypt") public class EncryptProperties {private final static String DEFAULT_KEY = "www.itboyhub.com"; private String key = DEFAULT_KEY; public String getKey () {return key;} public void setKey (String key) {this.key = key;}}

Here I set the default key is www.itboyhub.com,key is a 16-bit string, Songge this website address is just satisfied. In the future, if users want to configure key themselves, they only need to configure spring.encrypt.key=xxx in application.properties.

After all the preparatory work has been done, it is time for official encryption and decryption.

Because one of the very important purposes of Song GE's article is to share with you the use of ResponseBodyAdvice and RequestBodyAdvice. There is no problem with RequestBodyAdvice when doing decryption, while ResponseBodyAdvice has some limitations when doing encryption, but it does not have much impact. As I said earlier, if you want to control everything very flexibly, you should customize the filter. Here I will first use these two tools to achieve.

It is also important to note that ResponseBodyAdvice does not take effect until you use the @ ResponseBody annotation, and RequestBodyAdvice does not take effect until you use the @ RequestBody annotation, in other words, these two are useful when both ends interact with JSON. However, generally speaking, the scenarios of interface encryption and decryption are only possible when the front and rear ends are separated.

First, let's take a look at interface encryption:

EnableConfigurationProperties (EncryptProperties.class) @ ControllerAdvice public class EncryptResponse implements ResponseBodyAdvice {private ObjectMapper om = new ObjectMapper (); @ Autowired EncryptProperties encryptProperties; @ Override public boolean supports (MethodParameter returnType, Class > converterType) {return returnType.hasMethodAnnotation (Encrypt.class);} @ Override public RespBean beforeBodyWrite (RespBean body, MethodParameter returnType, MediaType selectedContentType, Class > selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {byte [] keyBytes = encryptProperties.getKey (). GetBytes () Try {if (body.getMsg ()! = null) {body.setMsg (AESUtils.encrypt (body.getMsg (). GetBytes (), keyBytes));} if (body.getObj ()! = null) {body.setObj (om.writeValueAsBytes (body.getObj ()), keyBytes)) }} catch (Exception e) {e.printStackTrace ();} return body;}}

We customize the EncryptResponse class to implement the ResponseBodyAdvice interface, and generics represent the return type of the interface. Here, we need to implement two methods:

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

Supports: this method is used to determine which interface needs to be encrypted. The parameter returnType indicates the return type. Our judgment logic here is whether the method contains @ Encrypt annotation. If so, it means that the interface needs encryption. If not, the interface does not need encryption.

BeforeBodyWrite: this method is executed before the data response, that is, we do secondary processing of the response data, and after the processing is complete, it will be converted to json return. The way we deal with it here is very simple. If the status in RespBean is a status code, there is no need to encrypt it. The other two fields can be re-encrypted and the values can be reset.

Also note that the custom ResponseBodyAdvice needs to be marked with the @ ControllerAdvice annotation.

Let's take a look at the interface decryption:

@ EnableConfigurationProperties (EncryptProperties.class) @ ControllerAdvice public class DecryptRequest extends RequestBodyAdviceAdapter {@ Autowired EncryptProperties encryptProperties; @ Override public boolean supports (MethodParameter methodParameter, Type targetType, Class > converterType) {return methodParameter.hasMethodAnnotation (Decrypt.class) | | methodParameter.hasParameterAnnotation (Decrypt.class);} @ Override public HttpInputMessage beforeBodyRead (final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class > converterType) throws IOException {byte [] body = new byte [inputMessage.getBody (). Available ()] InputMessage.getBody () .read (body); try {byte [] decrypt = AESUtils.decrypt (body, encryptProperties.getKey () .getBytes ()); final ByteArrayInputStream bais = new ByteArrayInputStream (decrypt); return new HttpInputMessage () {@ Override public InputStream getBody () throws IOException {return bais } @ Override public HttpHeaders getHeaders () {return inputMessage.getHeaders ();}};} catch (Exception e) {e.printStackTrace ();} return super.beforeBodyRead (inputMessage, parameter, targetType, converterType);}}

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

First of all, we notice that the DecryptRequest class does not directly implement the RequestBodyAdvice interface, but inherits from the RequestBodyAdviceAdapter class, which is a subclass of the RequestBodyAdvice interface, and implements some methods in the interface, so that when we inherit from RequestBodyAdviceAdapter, we only need to implement a few methods according to our actual needs.

Supports: this method is used to determine which interfaces need to handle interface decryption. The judgment logic here is the interface with @ Decrypt annotation on the method or parameter to deal with the decryption problem.

BeforeBodyRead: this method is executed before the parameter is converted to a specific object. We load the data from the stream, then decrypt the data, and then reconstruct the HttpInputMessage object to return after decryption.

Next, let's define an automatic configuration class, as follows:

@ Configuration @ ComponentScan ("org.javaboy.encrypt.starter") public class EncryptAutoConfiguration {}

There's nothing to say about this, it's relatively simple.

Finally, define the META-INF under the resources directory, and then define the spring.factories file, which is as follows:

Org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.javaboy.encrypt.starter.autoconfig.EncryptAutoConfiguration

In this way, the configuration class is automatically loaded when the project starts.

At this point, our starter development is complete.

two。 Package release

We can install the project to the local warehouse or publish it online for others to use.

2.1 install to local warehouse

It is easy to install to the local warehouse, mvn install directly, or in IDEA, click Maven on the right, and then double-click install, as follows:

2.2 publish online

If it can't be sent online, we can use JitPack to do it.

First of all, let's create a repository on GitHub and upload our code. I don't need to say much about this process.

After uploading successfully, click the Create a new release button on the right to release an official version, as follows:

After the release is successful, open jitpack, enter the full path to the repository, click the lookup button, find it, and then click the Get it button to complete the construction, as follows:

After the construction is successful, the project reference method is given on the JitPack:

Be careful to change the tag to your specific version number when quoting.

At this point, our tools have been successfully released! Friends can quote this starter in the following ways:

Com.github.lenve encrypt-spring-boot-starter 0.0.3 jitpack.io https://jitpack.io

3. Application

Let's create a normal Spring Boot project, introduce the web dependency, and then introduce the starter dependency we just had, as follows:

Org.springframework.boot spring-boot-starter-web com.github.lenve encrypt-spring-boot-starter 0.0.3 org.springframework.boot spring-boot-starter-test test jitpack.io https://jitpack.io

Then create an entity class for backup:

Public class User {private Long id; private String username; / / omit getter/setter}

Create two test interfaces:

@ RestController public class HelloController {@ GetMapping ("/ user") @ Encrypt public RespBean getUser () {User user = new User (); user.setId ((long) 99); user.setUsername ("javaboy"); return RespBean.ok ("ok", user) } @ PostMapping ("/ user") public RespBean addUser (@ RequestBody @ Decrypt User user) {System.out.println ("user =" + user); return RespBean.ok ("ok", user);}}

The first API uses the @ Encrypt annotation, so the data of the API is encrypted (if it is not used, the data is not encrypted). The second API uses @ Decrypt, so the uploaded parameters are decrypted. Note that the @ Decrypt annotation can be placed on either the method or the parameters.

Next, start the project for testing.

First test the get request interface:

As you can see, the returned data is encrypted.

Then test the post request:

As you can see, the encrypted data in the parameters has been restored.

If you want to modify the encryption key, you can add the following configuration to application.properties:

Spring.encrypt.key=1234567890123456

Encrypted data to the front end, the front end also has some js tools to deal with encrypted data, this later free to talk about js encryption and decryption.

At this point, I believe that "how to achieve Spring Boot interface parameters encryption and decryption" have a deeper understanding, might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report