spring boot中过滤器filter @WebFilter应用,返回值、限制某些ip

目录

过滤器

概念

在spring boot中的应用

基本应用

本人实际项目中的应用


过滤器

概念

进入业务逻辑前,可以同个filter预先增加部分功能。

  • 设置权限,限制某些ip的请求。

注:【本人实际项目中的应用可以参考】

在spring boot中的应用

基本应用

新增filter

@WebFilter(filterName = "permissionFilter", urlPatterns = "/*")
public class DemoFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("只在项目启动时执行一次");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("每次【规定的请求】都会到这里");
        //调用以下语句,表示通过了过滤器,调用本来的业务接口。
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("只在项目停止时执行一次");
    }
}

在spring boot项目启动类中增加注解

@ServletComponentScan

本人实际项目中的应用

  • 设置某些ip登陆权限,以及规定登陆次数。
  • 排除设置的url不经过过滤器。
  • 设置filter中不通过时的返回值,改正带中文乱码问题

过滤器

import com.alibaba.fastjson.JSONObject;
import com.bingo.achi.common.webBase.ObjectResponse;
import com.bingo.achi.utils.DateUtil;
import com.bingo.achi.utils.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Scheduled;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author gzb
 * @date 2021/9/2415:42
 */
@Order(1)
@WebFilter(filterName = "permissionFilter", urlPatterns = "/*")
public class PermissionFilter implements Filter {
    Logger logger = LoggerFactory.getLogger(PermissionFilter.class);

//规定以下的url直接通过
    private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("/swagger-resources", "/v3/swagger-login", "/v2/api-docs")));

    @Value("#{${permission.whiteIP}}")
    private Map<String, Integer> whiteIPMap;

    @Value("#{'${permission.alwaysIP}'.split(',')}")
    private List<String> alwaysIPList;

    private Map<String, Integer> whiteIPMapDay = new HashMap<>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        for (Map.Entry<String, Integer> entry : whiteIPMap.entrySet()) {
            whiteIPMapDay.put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String ipAddr = IpUtils.getIpAddr(request);
        logger.info("PermissionFilter 过滤器,请求ip为:{}", ipAddr);

        String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
        boolean contains = ALLOWED_PATHS.contains(path);
        res.setCharacterEncoding("utf-8");
        res.setContentType("text/html;charset=utf-8");
        try (PrintWriter printWriter = res.getWriter()){
            ObjectResponse objectResponse = new ObjectResponse();
            if (alwaysIPList.contains(ipAddr) && contains) {
                chain.doFilter(request, res);
            } else {
                if (whiteIPMapDay.containsKey(ipAddr)) {
                    Integer integer = whiteIPMapDay.get(ipAddr);
                    if (integer > 0) {
                        if (contains) {
                            res.reset();
                            chain.doFilter(request, res);
                        } else {
                            whiteIPMapDay.put(ipAddr, (whiteIPMapDay.get(ipAddr) - 1));
                            res.reset();
                            chain.doFilter(request, res);
                        }
                    } else {
                        objectResponse.setMessage("请求被拒绝,本IP:" + ipAddr + "每天只允许调用:" + whiteIPMap.get(ipAddr) + "次!");
                        objectResponse.setStatusCode(-1);
                        printWriter.write(JSONObject.toJSONString(objectResponse));
                    }
                } else {
                    objectResponse.setMessage("不支持本IP请求:" + ipAddr);
                    objectResponse.setStatusCode(-1);
                    printWriter.write(JSONObject.toJSONString(objectResponse));
                }
            }
        }
    }

    @Override
    public void destroy() {

    }
//每天恢复各个ip的限制次数
    @Scheduled(cron = "0 0 0 * * ?")
    public void initWhiteIPMapDay() {
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
        String format = sd.format(DateUtil.addDays(new Date(), -1));
        StringBuilder sb = new StringBuilder();
        sb.append("时间:" + format + ",whiteIP 各 IP 请求次数统计如下:").append("\n");
        for (Map.Entry<String, Integer> entry : whiteIPMapDay.entrySet()) {
            Integer num = whiteIPMap.get(entry.getKey());
            sb.append("ip:" + entry.getKey() + "请求次数:" + (num - entry.getValue())).append("\n");
            whiteIPMapDay.put(entry.getKey(), entry.getValue());
        }
        logger.info(sb.toString());

        //重新初始化
        for (Map.Entry<String, Integer> entry : whiteIPMap.entrySet()) {
            whiteIPMapDay.put(entry.getKey(), entry.getValue());
        }
    }
}

配置文件application.yml

permission:
  #key为ip,value是每天允许次数,每天0晨清零
  whiteIP: "{'127.0.0.1': 1, '192.168.16.30': 2}"
  #支持多个
  alwaysIP: 127.0.0.1,127.0.0.1

获取请求的ip

public static String getIpAddr(HttpServletRequest request){
        String ipAddress = request.getHeader("x-forwarded-for");
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
                //根据网卡取本机配置的IP
                InetAddress inet=null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
//                ipAddress= inet.getHostAddress();
                ipAddress= "127.0.0.1";
            }
        }
        //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
            if(ipAddress.indexOf(",")>0){
                ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

上一篇:ThreadLocal 应用及源码分析


下一篇:HashMap详解