在开发 Web 项目的时候,经常需要过滤器来处理一些请求,包括字符集转换什么的,记录请求日志什么的等等。在之前的 Web 开发中,我们习惯把过滤器配置到 web.xml 中,但是在 SpringBoot 中,兵没有这个配置文件,该如何操作呢?
1.编写一个过滤器:
import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @Slf4j @WebFilter(urlPatterns="/dyflight/*") public class IpFilter implements Filter{ /** * 默认限制时间(单位:ms)3600000,3600(s), */ private static final long LIMITED_TIME_MILLIS = 10 * 1000; /** * 用户连续访问最高阀值,超过该值则认定为恶意操作的IP,进行限制 */ private static final int LIMIT_NUMBER = 5; /** * 用户访问最小安全时间,在该时间内如果访问次数大于阀值,则记录为恶意IP,否则视为正常访问 */ private static final int MIN_SAFE_TIME = 5000; private FilterConfig config; @Override public void init(FilterConfig filterConfig) throws ServletException { this.config = filterConfig; //设置属性filterConfig } /* (non-Javadoc) * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @SuppressWarnings("unchecked") @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; ServletContext context = config.getServletContext(); // 获取限制IP存储器:存储被限制的IP信息 //Map<String, Long> limitedIpMap = (Map<String, Long>) context.getAttribute("limitedIpMap"); ConcurrentHashMap<String ,Long> limitedIpMap = (ConcurrentHashMap<String, Long>) context.getAttribute("limitedIpMap"); // 过滤受限的IP filterLimitedIpMap(limitedIpMap); // 获取用户IP String ip = IPUtil.getRemoteIpAddr(request); System.err.println("ip:"+ip); // 判断是否是被限制的IP,如果是则跳到异常页面 if (isLimitedIP(limitedIpMap, ip)) { long limitedTime = limitedIpMap.get(ip) - System.currentTimeMillis(); // 剩余限制时间(用为从毫秒到秒转化的一定会存在些许误差,但基本可以忽略不计) request.setAttribute("remainingTime", ((limitedTime / 1000) + (limitedTime % 1000 > 0 ? 1 : 0))); System.err.println("ip访问过于频繁:"+ip); throw new RuntimeException("ip访问过于频繁"); } // 获取IP存储器 ConcurrentHashMap<String, Long[]> ipMap = (ConcurrentHashMap<String, Long[]>) context.getAttribute("ipMap"); // 判断存储器中是否存在当前IP,如果没有则为初次访问,初始化该ip // 如果存在当前ip,则验证当前ip的访问次数 // 如果大于限制阀值,判断达到阀值的时间,如果不大于[用户访问最小安全时间]则视为恶意访问,跳转到异常页面 if (ipMap.containsKey(ip)) { Long[] ipInfo = ipMap.get(ip); ipInfo[0] = ipInfo[0] + 1; log.debug("当前第[" + (ipInfo[0]) + "]次访问"); if (ipInfo[0] > LIMIT_NUMBER) { Long ipAccessTime = ipInfo[1]; Long currentTimeMillis = System.currentTimeMillis(); log.debug("ip访问过于频繁:currentTimeMillis: "+currentTimeMillis+" - ipAccessTime:"+ipAccessTime+" : " + (currentTimeMillis - ipAccessTime) + "<="+ MIN_SAFE_TIME); if (currentTimeMillis - ipAccessTime <= MIN_SAFE_TIME) { limitedIpMap.put(ip, currentTimeMillis + LIMITED_TIME_MILLIS); request.setAttribute("remainingTime", LIMITED_TIME_MILLIS); log.debug("ip访问过于频繁:LIMITED_TIME_MILLIS:"+LIMITED_TIME_MILLIS); log.debug("ip访问过于频繁:"+ip); throw new RuntimeException("ip访问过于频繁"); } else { initIpVisitsNumber(ipMap, ip); } } } else { initIpVisitsNumber(ipMap, ip); System.out.println("您首次访问该网站"); } context.setAttribute("ipMap", ipMap); chain.doFilter(request, response); } @Override public void destroy() { // TODO Auto-generated method stub } /** * @Description 过滤受限的IP,剔除已经到期的限制IP * @param limitedIpMap */ private void filterLimitedIpMap(ConcurrentHashMap<String, Long> limitedIpMap) { if (limitedIpMap == null) { return; } Set<String> keys = limitedIpMap.keySet(); Iterator<String> keyIt = keys.iterator(); long currentTimeMillis = System.currentTimeMillis(); while (keyIt.hasNext()) { long expireTimeMillis = limitedIpMap.get(keyIt.next()); log.debug("expireTimeMillis <= currentTimeMillis:"+ expireTimeMillis+" <="+ currentTimeMillis); if (expireTimeMillis <= currentTimeMillis) { keyIt.remove(); } } } /** * @Description 是否是被限制的IP * @param limitedIpMap * @param ip * @return true : 被限制 | false : 正常 */ private boolean isLimitedIP(ConcurrentHashMap<String, Long> limitedIpMap, String ip) { if (limitedIpMap == null || ip == null) { // 没有被限制 return false; } Set<String> keys = limitedIpMap.keySet(); Iterator<String> keyIt = keys.iterator(); while (keyIt.hasNext()) { String key = keyIt.next(); if (key.equals(ip)) { // 被限制的IP return true; } } return false; } /** * 初始化用户访问次数和访问时间 * * @param ipMap * @param ip */ private void initIpVisitsNumber(ConcurrentHashMap<String, Long[]> ipMap, String ip) { Long[] ipInfo = new Long[2]; ipInfo[0] = 0L;// 访问次数 ipInfo[1] = System.currentTimeMillis();// 初次访问时间 ipMap.put(ip, ipInfo); } }
2. 创建一个监听器:需要初始化俩个容器:
import lombok.extern.slf4j.Slf4j; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import java.util.concurrent.ConcurrentHashMap; @Slf4j @WebListener public class MyApplicationListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { log.debug("liting: contextInitialized"); log.debug("MyApplicationListener初始化成功"); ServletContext context = sce.getServletContext(); // IP存储器 ConcurrentHashMap<String, Long[]> ipMap = new ConcurrentHashMap<>(); context.setAttribute("ipMap", ipMap); // 限制IP存储器:存储被限制的IP信息 ConcurrentHashMap<String, Long> limitedIpMap = new ConcurrentHashMap<String, Long>(); context.setAttribute("limitedIpMap", limitedIpMap); log.debug("ipmap:"+ipMap.toString()+";limitedIpMap:"+limitedIpMap.toString()+"初始化成功。。。。。"); } @Override public void contextDestroyed(ServletContextEvent sce) { // TODO Auto-generated method stub } }
3.iputil
import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; public class IPUtil { public static String getRemoteIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); 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(); if("127.0.0.1".equals(ip)||"0:0:0:0:0:0:0:1".equals(ip)){ //根据网卡取本机配置的IP InetAddress inet=null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ip= inet.getHostAddress(); } } return ip; } }
4配置
springboot启动类中添加过滤器和监听器的包扫描
@ServletComponentScan(basePackages="cn.xxx.common")
spring web.xml
过滤器
<filter> <filter-name>ipFilter</filter-name> <filter-class>com.xxxx.common.filter.IpFilter</filter-class> </filter> <filter-mapping> <filter-name>ipFilter</filter-name> <url-pattern>/dyflight/**</url-pattern> </filter-mapping>
监听器:
<listener> <listener-class>com.xxxx.common.Listener.MyApplicationListener</listener-class> </listener>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
时间:2020-04-13
1.新建maven项目 先新建一个maven项目,勾选上creat a simple project,填写groupid,artifactid 2.建立项目结构 3.添加依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE<
这篇文章主要介绍了Springboot jar文件如何打包zip在linux环境运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.添加打包配置文件 1.1 assembly.xml <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2
一, eclipse springboot打war包 1. 配置pom.xml文件 <packaging>war</packaging> <!-- 配置servlet,打war包时放开 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided
因为项目需要,需要在一个之前没做过springBoot项目的eclipse上跑一个springBoot项目并完成打包,所以就在网上查完资料以后搞了一下. 首先我们最好新开一个工作空间以免影响到其他项目,然后在新的工作空间进行操作.集成SpringBoot项目需要引入STS(springsource-tool-suite)插件.引入STS插件有两种方式,可选择以下其中一种进行集成: 第一种:在线下载 在eclipse中的商店自动下载安装TST,具体步骤为:Help -> Eclipse Markt
步骤一: 1.查看Eclipse版本的eclipse--help--About Eclipse,在Eclipseplatfrom那行的Version可以看到Eclipse版本号 在https://spring.io/tools/sts/all找你Eclipse对应版本 接着在Eclipse--help--Install New software 点击Add出现如下图 在Name:springboot ;Location:填你Eclispe对应版本的下载地址 如我的Eclipse是4.7.0.v版
Zipkin 简介 Zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in service architectures. Features include both the collection and lookup of this data. If you have a trace ID in a log file, you ca
spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.也就是说,Spring Boot是为了简化Spring开发而生,主要思想是降低spring的入门,使得新手可以以最快的速度让程序在spring框架下跑起来. 今天我们就来创建
1.ajax传过去的参数在controller接受不到 解决:在contoller中增加@RequestParam 例如:saveUploadFile( @RequestParam("file") MultipartFile file,HttpServletRequest request) 2.org.springframework.web.multipart.support.MissingServletRequestPartException: Required request pa
最近做的一个项目涉及到文件上传与下载.前端上传采用百度webUploader插件.有关该插件的使用方法还在研究中,日后整理再记录.本文主要介绍SpringBoot后台对文件上传与下载的处理. 单文件上传 // 单文件上传 @RequestMapping(value = "/upload") @ResponseBody public String upload(@RequestParam("file") MultipartFile file) { try { if (
spring boot 引入"约定大于配置"的概念,实现自动配置,节约了开发人员的开发成本,并且凭借其微服务架构的方式和较少的配置,一出来就占据大片开发人员的芳心.大部分的配置从开发人员可见变成了相对透明了,要想进一步熟悉还需要关注源码. 1.文件上传(前端页面): <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/lo
使用SpringBoot进行文件上传的方法和SpringMVC差不多,本文单独新建一个最简单的DEMO来说明一下. 主要步骤包括: 1.创建一个springboot项目工程,本例名称(demo-uploadfile). 2.配置 pom.xml 依赖. 3.创建和编写文件上传的 Controller(包含单文件上传和多文件上传). 4.创建和编写文件上传的 HTML 测试页面. 5.文件上传相关限制的配置(可选). 6.运行测试. 项目工程截图如下: 文件代码: <dependencies>
最近在学习SpringBoot,以下是最近学习整理的实现文件上传下载的Java代码: 1.开发环境: IDEA15+ Maven+JDK1.8 2.新建一个maven工程: 3.工程框架 4.pom.xml文件依赖项 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation
springmvc后端: @RequestMapping(value="scoreFileUpload",produces = "text/html; charset=utf-8") @ResponseBody public String upload(HttpSession session,@RequestParam("file1") MultipartFile file,@RequestParam("paperId") S
springboot上传文件大小的配置我这里记录两种,一种是设置在配置文件里只有两行代码,一种是加个Bean 首先第一种: application.properties中添加 spring.http.multipart.maxFileSize=10Mb spring.http.multipart.maxRequestSize=10Mb maxFileSize 是单个文件大小 maxRequestSize是设置总上传的数据大小 这就可以了. 根据自己需求定义吧,Mb和Kb都可以,大小写也都随意,L
我们在用ASP开发文件上传功能的时候,为了防止用户上传木马程序,常常会限制一些文件的上传,常用的方法是判断一下上传文件的扩展名是否符合规定,可以用right字符串函数取出上传文件的文件名的后四位,这样很容易就能判断了,但是这里面有一个漏洞,非常危险,就是chr(0)漏洞,详情请接着往下看. 一.首先解释下什么是chr(0)? 在ASP中可以用chr()函数调用ASCII码,其中chr(0)表示调用的是一个结束字符,简单的说当一个字符串中包含chr(0)字符时,只能输出chr(0)前面的字符,ch
整理文档,搜刮出一个SpringMvc MultipartFile实现图片文件上传示例,稍微整理精简一下做下分享. spring-servlet.xml <!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver&qu
基本的SpringMVC的搭建在我的上一篇文章里已经写过了,这篇文章主要说明一下如何使用SpringMVC进行表单上的文件上传以及多个文件同时上传的步骤 文件上传项目的源码下载地址:demo 一.配置文件: SpringMVC 用的是 的MultipartFile来进行文件上传 所以我们首先要配置MultipartResolver:用于处理表单中的file <!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver -->
html简单页面: index.html代码: <form action="{:U('index/upload')}" method="post" enctype="multipart/form-data"> 文件上传:<input type="file" name = "test[]"> 文件上传:<input type="file" name = &qu