Springboot拦截器实现IP黑名单

一·业务场景和需要实现的功能

以redis作为IP存储地址实现。

业务场景:针对秒杀活动或者常规电商业务场景等,防止恶意脚本不停的刷接口。

实现功能:写一个拦截器拦截掉黑名单IP,额外增加一个接口,将ip地址添加到redis中,并且返回redis中当前全部ip

二·Springboot中定义一个拦截器


@Order(0)
@Aspect
@Component
public class AopInterceptor { /**
* 定义拦截器规则
*/
@Pointcut("execution(* com.test.test.api.controller.test.test.*(..))")
public void pointCut() {
} /**
* 拦截器具体实现
*
* @throws Throwable
*/
@Around(value = "pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//判断是否为黑名单用户
String ip = getIpAddress(request);
if (checkIpBlack(ip)) {
//ip在黑名单中返回false
//return false;
DefaultResponse defaultResponse = new DefaultResponse();
defaultResponse.setCode(-1);
defaultResponse.setMessage("ip在黑名单中,拒绝访问.");
SysLogHelper.log("IpBlackAopInterceptor", "当前请求ip" + ip, "ip在黑名单中,拒绝访问");
return defaultResponse;
} else {
//ip不在黑名单中返回true
SysLogHelper.log("IpBlackAopInterceptor", "当前请求ip" + ip, "ip正常,允许访问");
return point.proceed();
} } catch (Exception e) {
e.printStackTrace();
SysLogHelper.error("IpBlackAopInterceptor黑名单拦截异常:", ExceptionUtils.getMessage(e) + "详细" + ExceptionUtils.getStackTrace(e), null);
}
return point.getArgs();
} //对比当前请求IP是否在黑名单中,注意(对比黑名单ip存放在redis中)
public boolean checkIpBlack(String ip) throws Exception {
IpBlackBody body = new IpBlackBody();
body = cacheHelper.get("IpBlack:ips", IpBlackBody.class);
if (body != null) {
for (int i = 0; i < body.getIp().length; i++) {
if (body.getIp()[i].equals(ip))
return true;
}
}
return false;
} }

三·获取请求主机IP地址

 public final static String getIpAddress(HttpServletRequest request)
throws IOException {
// 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
} return ip;
}

四·扩展接口,实现将黑名单IP写入redis当中,并返回当前所有黑名单IP

@RestController
public class IpBlackController { @Autowired(required = false)
private CacheHelper cacheHelper; @PostMapping("/testIpBlack")
public IpBlackBody IpBlack(@RequestBody IpBlackBody ipBlackBody) throws Exception { IpBlackBody body = new IpBlackBody();
body = cacheHelper.get("IpBlack:ips", IpBlackBody.class); if (body != null) {
//拼接当前IP与redis中现有ip
linkArray(body.getIp(), ipBlackBody.getIp());
//将数据赋给body
body.setIp(linkArray(body.getIp(), ipBlackBody.getIp()));
//setex中第二个参数时间为S,根据业务场景相应调整,此处我设置为一天
//将body中拼接后的ip地址数据写入redis中
cacheHelper.setex("IpBlack:ips", 86400, body); } else {
cacheHelper.setex("IpBlack:ips", 86400, ipBlackBody);
body = cacheHelper.get("IpBlack:ips", IpBlackBody.class);
return body;
}
return body;
} //拼接两个String[]的方法
public static String[] linkArray(String[] array1, String[] array2) { List<String> list = new ArrayList<>();
if (array1 == null) {
return array2;
}
if (array2 == null) {
return array1;
}
for (int i = 0; i < array1.length; i++) {
list.add(array1[i]);
}
for (int i = 0; i < array2.length; i++) {
list.add(array2[i]);
}
String[] returnValue = new String[list.size()];
for (int i = 0; i < list.size(); i++) { returnValue[i] = list.get(i);
}
return returnValue;
} }
总结:首先根据需要拦截的controller拦截响应请求controller层,然后根据编写相关拦截器的具体实现,其中包含两部主要操作:
1.获取到远程请求主机的实际ip地址
2.对比当前ip是否在黑名单中(此次操作需要读取redis中的黑名单ip列表)
然后根据当前需求增加了一个redis接口,实现将需要封禁的IP地址增加到redis黑名单中并返回当前所有的黑名单IP地址。
至此:至此springboot通过拦截器实现拦截黑名单功能已经实现。

Springboot拦截器实现IP黑名单的更多相关文章

  1. spring boot 学习(十二)拦截器实现IP黑名单

    拦截器实现IP黑名单 前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的”?秒防刷新”进行了一番修改.上次是采用注解加拦 ...

  2. SpringBoot自定义拦截器实现IP白名单功能

    SpringBoot自定义拦截器实现IP白名单功能 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/8993331.html 首先,相关功能已经上线了,且先让我先 ...

  3. Java结合SpringBoot拦截器实现简单的登录认证模块

    Java结合SpringBoot拦截器实现简单的登录认证模块 之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章 ...

  4. SpringBoot拦截器中Bean无法注入(转)

    问题 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于其他bean在service,controller层注入一点问题也没有,开始根本没意识到Be ...

  5. 【SpringBoot】SpringBoot拦截器实战和 Servlet3.0自定义Filter、Listener

    =================6.SpringBoot拦截器实战和 Servlet3.0自定义Filter.Listener ============ 1.深入SpringBoot2.x过滤器Fi ...

  6. SpringBoot拦截器中无法注入bean的解决方法

    SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...

  7. Springboot拦截器未起作用

    之前遇到要使用springboot拦截器却始终未生效的状况,查了网上的博客,大抵都是@Component,@Configuration注解未加,或是使用@ComponentScan增加包扫描,但是尝试 ...

  8. SpringBoot拦截器中service或者redis注入为空的问题

    原文:https://my.oschina.net/u/1790105/blog/1490098 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于 ...

  9. springboot + 拦截器 + 注解 实现自定义权限验证

    springboot + 拦截器 + 注解 实现自定义权限验证最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定义 ...

随机推荐

  1. MYSQL 中binlog 参数的记录

    http://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html binlog_cache_size Command ...

  2. JS 如何获取自定义属性

    <script>var testEle = document.getElementById("test"); testEle.setAttribute("de ...

  3. form提交(图片,excel其他文件)

    HTML表单需要设置enctype="multipart/form-data"这个属性,如果不这么设置,在提交表单时候,相关文件将无法获取. HTML表单如何打包数据文件是由enc ...

  4. poj1780欧拉回路

    转载 #include<cstdio> #include<cstring> ; bool vis[N]; char ans[N]; int main() { int n; wh ...

  5. html5做webAPP界面适配总结

    一.px em rem px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的. em是相对长度单位.相对于当前对象内文本的字体尺寸.如当前对行内文本的字体尺寸未被人为设置,则相 ...

  6. 用python selenium 单窗口单IP刷网站流量脚本

    近期有朋友说需要增加自己网站的流量,故用python写了一个简单的脚本,配合IP池或者动态IP都可以刷,当然最爽的是单窗口单IP. 说明 作弊可耻! 环境 python3.8 + selenium + ...

  7. 一文带你学会基于SpringAop实现操作日志的记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人, ...

  8. 派生类Student的构造函数和析构函数 代码参考

    #include <iostream> #include <cstring> using namespace std; class Person { private: char ...

  9. webmin RCE漏洞利用及分析

    Webmin是目前功能最强大的基于Web的Unix系统管理工具.管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作. 利用条件:webmin <= 1.910 原因:官网 Sou ...

  10. Bom和Dom对象

    BOM-JavaScript是运行在浏览器中的,所以提供了一系列对象用于和浏览器窗口进行交互,这些对象主要包括window.document.location.navigator和screen等.通常 ...