Redian新闻
>
SpringBoot接口添加IP白名单限制

SpringBoot接口添加IP白名单限制

公众号新闻

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:blog.csdn.net/second_place_zyj
/article/details/130320957


实现流程: 自定义拦截器——注入拦截器——获取请求IP——对比IP是否一致——请求返回

文章背景: 接口添加IP白名单限制,只有规定的IP可以访问项目。

实现思路: 添加拦截器,拦截项目所有的请求,获取请求的网络IP,查询IP是否在白名单之中,白名单设置在数据库中,用一张表存储,若在表中有此IP则进行下一步,不在则进行请求拦截,返回到客户端。

实现方式: HandlerInterceptor+MySQL+Mybatis-plus

自定义拦截器,创建类并且实现HandlerInterceptor接口,即可成为拦截器。

HandlerInterceptor接口提供了三个方法,三个方法分别如下

HandlerInterceptor接口提供了三个方法,三个方法分别如下
preHandle方法在业务处理器处理请求之前进行调用,可以用做权限校验,token验证等等。结果返回true继续执行,结果返回false拦截请求。
postHandle方法在业务处理器处理请求执行完成后,生成视图之前执行。
afterCompletion方法在业务处理器执行完成之后,可以用做清理资源,日志记录等等。

自定义拦截器:实现HandlerInterceptor接口,重写preHandle方法,在preHandle添加获取IP的方法和IP检验业务。代码中涉及到的testEngineerService.getIp()方法在下边!!!

import com.alibaba.fastjson.JSON;
import com.lifel.service.TestEngineer.TestEngineerService;
import com.lifel.utils.ToolsResultEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
 
/********************************************************************************
 ** @author :ZYJ
 ** @date :2023/04/23
 ** @description :自定义拦截器 拦截ip
 *********************************************************************************/
@Slf4j
public class WhiteListIntercept implements HandlerInterceptor {
 
    @Autowired
    private TestEngineerService testEngineerService;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ipAddress = null;
        try {
            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")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) {
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        log.info("机主的ip是"+ipAddress);
        WebApplicationContext cxt = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        if(cxt != null && cxt.getBean(TestEngineerService.class) != null &&testEngineerService == null) {
            testEngineerService =cxt.getBean(TestEngineerService.class);
        }
        if(testEngineerService.getIp(ipAddress)){
            return true;
        }else{
            returnJson(response, JSON.toJSONString(new ToolsResultEntity(1002, "ip不存在", null)));
            return false;
        }
    }
 
    /********************************************************************************
     ** @author :ZYJ
     ** @date :2023/04/23
     ** @description :设置请求拦截返回参数
     *********************************************************************************/
    private void returnJson(HttpServletResponse response, String result) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(result);
        } catch (IOException e) {
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}

注入拦截器:将拦截器注入到spring,交给spring管理

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
 
    /********************************************************************************
     ** @author :ZYJ
     ** @date :2023/04/23
     ** @description :配置拦截器
     *********************************************************************************/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//       下面这句代码相当于添加一个拦截器,添加的拦截器就是我们刚刚创建的
        registry.addInterceptor(new WhiteListIntercept())
//       addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源
                .addPathPatterns("/**");
    }
}

创建Service和实现类

public interface TestEngineerService {
 
    /********************************************************************************
     ** @author :ZYJ
     ** @date :2023/04/23
     ** @description :查询IP是否在白名单中
     *********************************************************************************/
    Boolean getIp(String name);
 
}
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lifel.entity.TestEngineer.WhiteIp;
import com.lifel.mapper.TestEngineer.WhiteIpMapper;
import com.lifel.service.TestEngineer.TestEngineerService;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
 
@Service
public class TestEngineerServiceImpl implements TestEngineerService {
 
    @Resource
    private WhiteIpMapper whiteIpMapper;
 
    /********************************************************************************
     ** @author :ZYJ
     ** @date :2023/04/23
     ** @description :查询IP是否在数据库中保存
     *********************************************************************************/
    @Override
    public Boolean getIp(String name) {
        try {
            //查询表中是否有此IP,并且状态是打开的状态
            WhiteIp whiteIp = whiteIpMapper.selectOne(new QueryWrapper<WhiteIp>().eq("name", name).eq("state""open"));
            if(whiteIp==null){
                return false;
            }else{
                return true;
            }
        }catch (Exception e){
            return false;
        }
    }
}

测试代码,创建Controller,调用方法进行测试

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping(value = "/api")
@Api(value = "测试类", tags = "测试类")
public class TestEngineerController {
 
    @GetMapping("/test")
    @ApiOperation(value = "测试IP白名单是否生效")
    public String test() {
        return "ok";
    }
}

查看我们的IP地址,保存到数据库中,以保证只有我们自己的IP才能访问项目接口

表中保存我们正确的IP,启动项目访问测试方法,请求结果正常返回!!!

表中保存一个错误的IP,启动项目访问测试方法,请求拦截提示IP不存在!!!

注意:测试的时候不能写localhost,必须是127.0.0.1:8080,127.0.0.1获取的才是我们本地的IP,localhost获取的为0:0:0:0:0:0:0:1


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
【行业日报】Springer宣布和微软进行云应用合作!特斯拉空头投资者四天损失达55亿美金!【活动】PG 2024 Spring活动回顾Life is ten thousand beautiful spring scenerySpaceX 泄露近150GB数据,以及三千份图纸这些年背过的面试题——SpringCloud篇[评测]Redmi Book Pro 16 2024 评测BB鸭 | 滴滴整顿顺风车;苹果称128GB的iPhone也有充裕空间;李斌表示蔚来手机是防御策略;PS5 Pro泄露【LEAP ACE】| Sign-Up the Consulting Boot Camp一地鸡毛(5)惠普星 Book Pro 14 2024 笔记本锐龙版上架:可选 R5-8645H / R7-8845H,4999 元起余承东:Pura 70 过两天有好消息/文心一言用户数量破 2 亿/iPhone 16 Pro 或以 256 GB 存储起步《巴郞笔谈》005:杨家花园如何通过内网穿透实现外部网络对 SpringBoot 接口的 HTTP 监听和调试?Booking官网订房被骗近3000镑?骗子挑衅:谢谢你的钱spring是“春天”,chicken是“鸡”,那spring chicken什么意思?CVPR 2024 | 基于MoE的通用图像融合模型,添加2.8%参数完成多项任务香港科技大学(广州)招收多名2024Fall/2025Spring博士生/研究助理/博士后湖南大学聂舟团队Angew |工程化Anti-CRISPR蛋白创建CRISPR-Cas蛋白开关用于激活型基因编辑和病毒蛋白酶检测消息称英伟达 Blackwell“B100”GPU 将配 192GB HBM3e 显存,B200 配 288GB 显存俄罗斯将同性恋、双性恋与跨性别者(LGBT)运动列入恐怖分子名单祈求[评测]ASUS ProArt GeForce RTX 4080 Super OC Edition 16GB GDDR6X 评测《甲辰龙年元宵五联》巴郞GOLANG接口三个特性24GB单卡全量微调Llama 3-8B,仅需添加一行代码SpringBoot Redis 分布式锁的正确实现方式【明天开课】ACT接纳承诺疗法核心技术应用 | 创始人海斯亲授&永久回看Fare Game: Why China’s Ride-Share Boom Is Leaving Drivers Behind《辛苦》巴郞雷神 AIbook 15 轻薄本上架预约:OCuLink 接口、RGB 背光键盘、酷睿 Ultra7Spring Boot 3.2 和 Spring Framework 6.1添加对 Java 21、虚拟线程和 CRaC 的支持BB鸭 | 华为终端与中国珠宝签约合作;小米Civi 4 Pro发布;李想承认误判纯电战略节奏;马斯克脑机接口患者康复iPhone 16 Pro存储或以256GB起步/余承东:Pura70过两天有好消息/OpenAI CEO:AI成本可降至接近零Property to Virtual Goods, More Young Chinese Are Drafting Wills惠普星 Book Pro 16 2024 笔记本上架:酷睿 Ultra + RTX 4050,80W 整机性能释放
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。