拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密

1.拦截器实现指定的IP白名单进行访问规定的Controller

需求:只允许内网的IP(也就是IP白名单)进行访问VideoController和ImgController,其余的FontController可以随便访问不做限制
总体的项目结构:
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第1张图片

1.1、先写好业务代码三个Controller

访问的路径分别是:

/api/video/video1
/api/img/img1
/api/font/font1

拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第2张图片

package com.cao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/font")
public class FontController {
    @RequestMapping("/font1")
    public String getFont(){
        return "This is a font!";
    }
}
package com.cao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/img")
public class ImgController {
    @RequestMapping("/img1")
    public String getImg(){
        return "This is a img!";
    }
}
package com.cao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/video")
public class VideoController {
    @RequestMapping("/video1")
    public String getVideo(){
        return "This is a video!";
    }
}

1.2、进行ip白名单的配置

在yml文件中进行配置要放行的IP白名单,是一个List

server:
  port: 8888
myapp:
  allowedIps:
    - 127.0.0.3
    - 127.0.0.2

1.3、针对上面的yml配置写获取白名单的类

用于接收yml中配置的IP白名单,注意配置和属性之间的名称要一致:myapp.allowedIps

package com.cao.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 该类用于接收yml中配置的IP白名单
 */
@Data
@Component
@ConfigurationProperties(prefix = "myapp")
public class WhiteIpProperties {
	private List<String> allowedIps;
}

1.4、定义拦截器

这里的需求是打印出来访问VideoController和ImgController的非白名单的IP并设置返回状态为 403
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第3张图片

package com.cao.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 定义拦截器以及执行时候的业务代码
 */
@Slf4j
public class IpAddressInterceptor implements HandlerInterceptor {
    private List<String> allowedIps;

    public IpAddressInterceptor(List<String> allowedIps) {
        this.allowedIps = allowedIps;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ipAddress = request.getRemoteAddr();
        if (allowedIps.contains(ipAddress)) {
            return true;
        } else {
            log.info("该ip不在访问的白名单中:{}", ipAddress);
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }
    }
}

1.5、注册拦截器

注册拦截器的时候进行配置访问路径,在WebMvcConfig中addPathPatterns中加上要限制的url
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第4张图片

package com.cao.config;

import com.cao.interceptor.IpAddressInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * 用于注册拦截器
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private WhiteIpProperties whiteIpProperties;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> allowedIps = whiteIpProperties.getAllowedIps();
        registry.addInterceptor(new IpAddressInterceptor(allowedIps))
                .addPathPatterns("/api/video/**", "/api/img/**")
                .excludePathPatterns("/error");
    }
}

1.6、测试

1.6.1、测试127.0.0.1不在黑名单中的场景

我们现在配置的白名单是:127.0.0.2、127.0.0.3,所以用127.0.0.1是访问不到VideoController和ImgController中对应的url,但是可以访问到FontController中的url
访问VideoController和ImgController,返回的状态是403,看到打印的日志
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第5张图片

拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第6张图片
访问FontController中的url,是不受影响的
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第7张图片

1.6.2、测试127.0.0.1在黑名单中的场景

将127.0.0.1加入到白名单中,再次测试,三个Controller都应该能够访问到
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第8张图片
进行访问:
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第9张图片
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第10张图片
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第11张图片
OK 测试没有问题。

2.对返回的结果进行加密

新加一个包
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第12张图片

package com.cao.advice;

import lombok.extern.slf4j.Slf4j;
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.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Component
@RestControllerAdvice
@Slf4j
public class EncryptionResponseBodyAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true; //对所有请求进行处理
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class selectedConverterType,
                                  ServerHttpRequest request,
                                  ServerHttpResponse response) {
        ServletServerHttpRequest httpRequest = (ServletServerHttpRequest) request;
        log.info("调用uri:{}", httpRequest.getServletRequest().getRequestURI());
        String bodyString = (String) body;
        log.info("没有加密的string:{}", bodyString);
        //对返回结果进行加密
        String encryptedBody = encryptBody(body);
        log.info("加密后的encryptedBody:{}", encryptedBody);
        return encryptedBody;
    }

    private String encryptBody(Object body) {
        String string = body.toString();
        byte[] encryptedBytes = Base64.getEncoder().encode(string.getBytes(StandardCharsets.UTF_8));
        return new String(encryptedBytes, StandardCharsets.UTF_8);
    }
}

获取到返回体
调用加密方法
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第13张图片
拦截器实现指定的IP白名单进行访问规定的Controller、对返回的结果进行加密_第14张图片

你可能感兴趣的:(SpringBoot,java,spring,boot,后端,拦截器,ip访问)