目录
过滤器
概念
在spring boot中的应用
基本应用
本人实际项目中的应用
进入业务逻辑前,可以同个filter预先增加部分功能。
注:【本人实际项目中的应用可以参考】
新增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
过滤器
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; }