当前位置:首页 > 技术文章 > 正文内容

不想被恶意访问?SpringBoot 的 IP 白名单限制了解一下!

arlanguage5个月前 (12-18)技术文章41

前言

在项目开发中,我们多少都会遇到要对请求访问IP做限制,允许哪些IP是可以访问系统。对于前后分离项目有两种方案,第一种是在Nginx服务中进行配置IP白名单,第二种是项目接口中进行白名单控制,例如在spring boot接口中进行白名单限制。

方案一:Nginx服务器中配置IP白名单限制

如果想在nginx做IP白名单限制访问,需要使用两个关键词,allow和deny;在nginx中,allow和deny是必须结合使用。

  • allow: 表示允许访问,即白名单;
  • deny: 表示禁止访问,即黑名单。

allow和deny可以配置http、server和location模块中。

注意:allow必须放在deny前面,否则会无效

详细案例如下

location模块:

server {
    listen 8059;
    server_name xxx.xxx.com;
    charset utf-8;

    location /api {
     allow 192.168.183.89;
        deny all;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:9659/api;

        proxy_read_timeout 259200;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    location /manage {
        allow 192.168.183.89;
        deny all;
        .......
    }
    ......
}

server模块:

server {
    listen 8059;
    server_name xxx.xxx.com;
    charset utf-8;
    
    allow 192.168.29.36;
    allow 192.168.30.26;
    ......
    deny all;

 location /api {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:9659/api;

        proxy_read_timeout 259200;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
 }
}

http模块:

http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8,gbk; 
    client_max_body_size 1024m;
    client_body_buffer_size 300k;

    sendfile        on;
    tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    
    allow 192.168.56.92;
    allow 192.168.89.129;
    ......
    deny all;

 server {
     listen 8059;
     server_name xxx.xxx.com;
     charset utf-8;

  .....
 }
}

在Nginx配置IP白名单或黑名单,有个缺点就是每次配置完后都需要重启Nignx

方案二:在springboot中,自定义过滤器实现HandlerInterceptor

实现流程: 创建表实现IP查询对比接口自定义拦截器获取请求IP对比IP是否在白名单中请求返回

实现方式: Spring boot3 + Mysql8.0 + Mybatis-Flex

1、创建白名单管理表

CREATE TABLE `sh_sys_white_list` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `ip` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ip地址',
  `is_white` tinyint DEFAULT NULL COMMENT '是否白名单(1:是,2:否)',
  `create_by` bigint DEFAULT NULL COMMENT '创建人',
  `create_at` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` bigint DEFAULT NULL COMMENT '更新人',
  `update_at` datetime DEFAULT NULL COMMENT '更新时间',
  `deleted` tinyint DEFAULT NULL COMMENT '逻辑删除(0:正常,1:删除)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='白名单管理表';

自定义Mapper继承BaseMapper,自定义Service继承IBaservice、Impl继承BaseServiceImpl<Mapper, T>实现自定Service接口类。

package com.zhush.admin.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.zhush.admin.entity.SysWhiteList;
import com.zhush.admin.mapper.SysWhiteListMapper;
import com.zhush.admin.service.ISysWhiteListService;
import com.zhush.common.service.BaseServiceImpl;
import org.springframework.stereotype.Service;

import java.util.Objects;

import static com.zhush.admin.entity.table.SysWhiteListTableDef.SYS_WHITE_LIST;

/**
 * @ClassName SysWhiteListServiceImpl
 * @Description TODO
 * @Author zhush
 * @Date 2024/4/26 0026 14:20
 **/
@Service
public class SysWhiteListServiceImpl extends BaseServiceImpl<SysWhiteListMapper, SysWhiteList> implements ISysWhiteListService {

    /**
     * 查找请求ip是否是白名单中
     * @param ip
     * @return
     */
    @Override
    public boolean getWhiteListByIp(String ip) {
        QueryWrapper wrapper = QueryWrapper.create().where(SYS_WHITE_LIST.IP.eq(ip));
        SysWhiteList sysWhiteList = this.mapper.selectOneByQuery(wrapper);
        if (sysWhiteList != null && Objects.equals(sysWhiteList.getIsWhite(), 1)) {
            return true;
        } else {
            return false;
        }
    }

}

2、自定义WhiteListHandlerInterceptor过滤器,实现HandlerInterceptor类

在自定义过滤中,重写preHandle方法,在preHandle方法中对比IP,具体实现如下:

package com.zhush.admin.handler;

import com.zhush.admin.service.ISysWhiteListService;
import com.zhush.common.enums.ResultCodeEnum;
import com.zhush.common.utils.IpUtils;
import com.zhush.common.utils.JacksonUtils;
import com.zhush.common.utils.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * @ClassName WhiteListHandlerInterceptor
 * @Description 白名单 处理器拦截器
 * @Author zhush
 * @Date 2024/4/26 0026 13:59
 **/
public class WhiteListHandlerInterceptor implements HandlerInterceptor {

    @Resource
    private ISysWhiteListService whiteListService;

    @Value("${zhush.white.enable}")
    private boolean enable;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!enable) {
            return true;
        }
        String ipAddr = IpUtils.getIpAddr(request);
        boolean whiteListByIp = whiteListService.getWhiteListByIp(ipAddr);
        if (whiteListByIp) {
            return true;
        } else {
            result(response, JacksonUtils.toJSONString(Result.build("IP不在白名单内", ResultCodeEnum.ERROR)));
            return false;
        }
    }

    private void result(HttpServletResponse response, String result) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}

IpUtils工具类

package com.zhush.common.utils;

import jakarta.servlet.http.HttpServletRequest;

/**
 * @ClassName IpUtils
 * @Description ip获取工具类
 * @Author zhush
 * @Date 2024/4/26 0026 14:34
 **/
public class IpUtils {

    private static final String UNKNOWN = "unknown";

    public static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return UNKNOWN;
        }

        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        String[] ips = ip.split(",");
        return ips[0].trim();
    }

}

3、自定义WebMvcConfig类,实现WebMvcConfigurer

在自定义的WebMvcConfig配置类中,注入WhiteListHandlerInterceptor拦截器。

package com.zhush.admin.config;

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.zhush.admin.handler.WhiteListHandlerInterceptor;
import com.zhush.common.mapper.CustomerObjectMapper;
import org.springframework.context.annotation.Bean;
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;

/**
 * @ClassName ZhushWebMvcConfig
 * @Description TODO
 * @Author zhush
 * @Date 2024/2/3 0003 20:55
 **/
@Configuration
public class ZhushWebMvcConfig implements WebMvcConfigurer {

    @Bean
    public WhiteListHandlerInterceptor whiteListHandlerInterceptor() {
        return new WhiteListHandlerInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(whiteListHandlerInterceptor());
    }

}

使用拦截器实现白名单的好处是不要重启任何服务器,只需要在往数据库表中添加白名单即可。

扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/299.html

标签: nginx配置ci
分享给朋友:

“不想被恶意访问?SpringBoot 的 IP 白名单限制了解一下!” 的相关文章

nginx代理常用配置

1. 最简反向代理配置在http节点下,使用upstream配置服务地址,使用server的location配置代理映射。upstream my_server { server 10.0.0.2:8080; keepalive 2000;}server { listen 80; server_...

ThinkPhp6从安装到配置全解

Thinkphp6已经不支持之前安装方式了,只能使用Composer安装,对于V6的新用户来说,真希望有个全过程手册,我就分享一下我自己安装使用的过程,供参考。一、安装Composer在 Linux 和 Mac OS中可以运行如下命令:curl -sS https://getcomposer.org...

压测nginx出现的问题分析

压测nginx出现no live upstreams while connecting to upstream的问题分析基础环境版本信息Centos 7.1nginx version: openresty/1.13.6.2nginx配置信息stream {   ...

K8S灰度环境频繁出现502 k8s ingress 灰度发布

公司一个需求版本开发、测试结束,升级到灰度环境之后频繁出现502公司使用的是php + nginx 所以分析也是按照这个方向来分析的。nginx报错:NGINX ERROR 10.9.95.75 !!!2020/07/21 17:05:12 [error] 7#7: *38808 recv() fa...

一般人绝对无法发现的nginx锅

nginx热启动:nginx -s reloadPS:要在/etc/profile环境变量PATH里配置nginx的路径。配置完执行 source /etc/profile 让变量生效。 一次部署,同样的前端代码,放到了nginx里面运行,但是有一个模块全部页面都报这个错误,其他模块正常展示。以前遇...

「网络」运维需要掌握的 17 个实用技巧

1、查找当前目录下所有以.tar结尾的文件然后移动到指定目录find . -name “*.tar” -execmv {}./backup/ ;注解:find –name 主要用于查找某个文件名字,-exec 、xargs可以用来承接前面的结果,然后将要执行的动作,一般跟find在一起用的很多,fi...