目录
过滤器
概念
进入业务逻辑前,可以同个filter预先增加部分功能。
- 设置权限,限制某些ip的请求。
注:【本人实际项目中的应用可以参考】
在spring boot中的应用
基本应用
新增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
本人实际项目中的应用
- 设置某些ip登陆权限,以及规定登陆次数。
- 排除设置的url不经过过滤器。
- 设置filter中不通过时的返回值,改正带中文乱码问题
过滤器
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;
}