Implement interface encryption

1. Reasons for demand

As shown in the figure, if the address is exposed, anyone who gets the address can directly send the request, but the front-end sending request must be realized through http. Therefore, the address will be exposed and interested people will get the address. Therefore, it is necessary to add a sign signature. The way to generate the signature is unknown to others, This will ensure that others can't use the address

2 encryption principle

When the client sends a packet to the server, it will generate a signature a based on the packet and send it together. When the server receives the packet, it will also generate a signature B based on the packet, and compare the signatures A and B. if the two are the same, it is considered that the packet is indeed sent legally by the client, and the server will respond to the request. If the signatures are inconsistent, Indicates that the data of the packet has been temporarily tampered with

The most important thing in the whole process is to implement encryption based on data packets. Therefore, the sign signature is not used as any field, but based on certain encryption rules. This encryption rule focuses on confidential data both on the client and the server

3 signature timeliness

The sign signature should be time-effective. Otherwise, if someone intercepts a single request and sends the request to the server 100 times, there will be trouble. For example, if the user wanted to send a paid prop, he was intercepted and sent the request repeatedly, which will become asking the client to send 100 gifts, and the user's money will be gone.

There are two ways to achieve timeliness:

  1. After the user logs in, the server issues the token to which the user belongs. Each user is different. The token is used as the encryption secret key in the signature generation rules. Because the token has a validity period, the generated signature can also be time-effective. However, in this way, two-layer encryption must be done. The token returned after login must be encrypted and cannot be returned in plaintext, and then the data packet can be encrypted normally

  2. Make the request carry a timestamp. The request response time and timestamp must not exceed XX seconds, which is equivalent to setting the expiration time for the signature. Assuming that the expiration time is set to 2 seconds, the signature expires just after the request is intercepted and before it is packaged and sent, which realizes timeliness

If you encounter a malicious request attack, you need to use a dynamic filter, which is another solution. It is not the same thing as the signature aging performance

4. Selective encryption (dynamic signature verification)

Not all interfaces need to be encrypted, such as the number of people in the room and the gift data. There is no need to encrypt these. Only very important functions, such as payment and recharge, need to be encrypted

To implement encryption, you need to generate a signature and complete the comparison before the request reaches the controller, so you need to set an interceptor

5 implementation mode

5.1 create a simple interceptor

Write the interceptor under the common module

First create an interceptor

Then configure the interceptor in the spring configuration class

@Configuration
public class DefaultConfig implements WebMvcConfigurer {

    Logger logger = LoggerFactory.getLogger(DefaultConfig.class);
    @Resource
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**")
        .excludePathPatterns("/login/**");
    }
}

5.2 sort out the data intercepted by the interceptor

Now, if the front end requests the interface directly, it will be intercepted by the interceptor

The interceptor can identify the interface and specific method to be accessed by the request, and can also see whether there are annotations on this method and what annotations there are. Then we only need to customize an annotation and put it on the method to be encrypted. When the filter finds that the front-end request wants to access the method with this annotation, it will intercept it, so as to realize dynamic signature verification, Only important methods are verified

5.3 user defined annotation

Customize an annotation in the public module, and set the life cycle, annotation type and a boolean variable

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
    boolean isCheck() default true;
}

As shown in the figure, this annotation is placed on the method that needs to be encrypted to achieve the purpose of fixed-point interception

5.4 complete the preparation of filter

5.4.1 annotation of acquisition method

The filter can obtain the annotation of the requested method based on the method shown in the figure

5.4.2 user defined encryption method

  • Extension: sorting by TreeMap

The code is shown in the figure

The effect is shown in the figure

As long as the encryption method is complex enough, it is difficult for others to obtain and crack it. There is no fixed saying

For example, we set an encryption method, first sort the attributes in the packet according to A-Z or Z-A, and then convert them into strings. Using TreeMap, we can realize A-Z or Z-A sorting

Then take out the ordered attributes one by one and spell them into a string, which is similar to the effect in the figure below. In the figure, C is an array, so there are multiple values, and the values are separated by commas

The code is as follows. After splicing the attributes, finally splice the token sent to the user by the server after the user logs in. In this way, when a signature mismatch is found, the token can be recorded and traced back to the user who sent false data. Then, the user can be sealed or the alarm can be sent to the network police for processing

Finally, encrypt the string sb and compare it with the signature in the packet sent by the front end. If the comparison is correct, it will be released

5.4.3 filter code

The overall code is as follows

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //Gets the annotation on the requested method
        Auth methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(Auth.class);
        //If the @ Auth annotation can be obtained and the isCheck of the annotation is true, intercept and verify it
        if(methodAnnotation != null && methodAnnotation.isCheck()){
            //verification
            Map<String, String[]> parameterMap = request.getParameterMap();
            TreeMap<String, String[]> treeMap = new TreeMap<>(parameterMap);
            StringBuilder sb = new StringBuilder();
            treeMap.forEach((s, strings) -> {
                if(!s.equals("sign")){
                    sb.append(s);
                    sb.append("=");
                    sb.append(strings);
                    sb.append("&");
                }
            });
            sb.append("token="+"asdasdasdasdasdas");
            //This step: implement MD5 encryption with the help of hutool tool class to obtain the signature A of the server
            //Get the signature B passed by the front end
            String sign = request.getParameter("sign");
            //This step: compare the signatures of the front end and the server before releasing the request
        }
        return false;
    }
}

Posted by vipes on Sun, 31 Oct 2021 05:41:00 -0700