在springboot项目中如何设计UrlFilter过滤器

1、在我们Web项目中需要对非法Url和请求参数进行过滤拦截,所以就得配置一个UrlFilter过滤器,具体配置如下所示

 一、创建UrlFilter配置类

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@WebFilter(filterName = "urlFilter",urlPatterns = "/*")
@Component
public class UrlFilter implements Filter {
    private static Logger log = LoggerFactory.getLogger(UrlFilter.class);
    @Autowired
    IpAddressService ipAddressService;//IP服务类
    public void destroy() { }

    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setCharacterEncoding("UTF-8");
        String requestStr = getRequestString(request);
        log.info("");
        log.info("==============================THIS IS NEW REQUEST===================================");
        log.info("完整的地址是========" + request.getRequestURL().toString());
        log.info("提交的方式是========" + request.getMethod());
        IpInfo ipInfo = getIp(request);                             //获取用户IP信息
        log.info("请求IP地址是========" + ipInfo.getIp()+",浏览器:"+ipInfo.getUa());
        if ("bingo".equals(guolv2(requestStr))
                || "bingo".equals(guolv2(request.getRequestURL().toString()))) {
            log.info("访问地址发现非法字符,已拦截======其非法地址"+request.getRequestURL().toString());
            PrintWriter writer = response.getWriter();
            writer.print("访问地址发现非法字符");
            writer.close();
            return;
        }
        // 允许以下主机ip或域名和端口允许访问 
        String myhosts = request.getHeader("host");
        if (!StringUtils.equals(myhosts, "127.0.0.1")//特定ip
                && !StringUtils.equals(myhosts, "127.0.0.1:8080")//特定ip和端口
                && !StringUtils.equals(myhosts, "localhost:8080")) {
            log.info("访问host非法,已拦截======其非法host为:"+myhosts);
            PrintWriter writer = response.getWriter();
            writer.print("访问host非法,已拦截");
            writer.close();
            return;
        }

        // 过滤请求特殊字符,扫描跨站式漏洞
        Map parameters = request.getParameterMap();
        if (parameters != null && parameters.size() > 0) {
            for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
                String key = (String) iter.next();
                String[] values = (String[]) parameters.get(key);
                for (int i = 0; i < values.length; i++) {
                    values[i] = guolv(values[i]);
                    log.info("参数:{}===》值:{}",key,values[i]);
                }
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);

    }

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public static String guolv(String a) {
        a = a.replaceAll("%22", "");
        a = a.replaceAll("%27", "");
        a = a.replaceAll("%3E", "");
        a = a.replaceAll("%3e", "");
        a = a.replaceAll("%3C", "");
        a = a.replaceAll("%3c", "");
        a = a.replaceAll("<", "");
        a = a.replaceAll(">", "");
        a = a.replaceAll("\"", "");
        a = a.replaceAll("'", "");
        a = a.replaceAll("\\+", "");
        a = a.replaceAll("\\(", "");
        a = a.replaceAll("\\)", "");
        a = a.replaceAll(" and ", "");
        a = a.replaceAll(" or ", "");
        a = a.replaceAll(" 1=1 ", "");
        return a;
    }

    private String getRequestString(HttpServletRequest req) {
        String requestPath = req.getServletPath().toString();
        String queryString = req.getQueryString();
        if (queryString != null)
            return requestPath + "?" + queryString;
        else
            return requestPath;
    }

    public String guolv2(String a) {
        if (StringUtils.isNotEmpty(a)) {
            if (a.contains("%22") || a.contains("%3E") || a.contains("%3e")
                    || a.contains("%3C") || a.contains("%3c")
                    || a.contains("<") || a.contains(">") || a.contains("\"")
                    || a.contains("'") || a.contains("+") || /*
             * a.contains("%27")
             * ||
             */
                    a.contains(" and ") || a.contains(" or ")
                    || a.contains("1=1") || a.contains("(") || a.contains(")")) {
                return "bingo";
            }
        }
        return a;
    }

    public IpInfo getIp(HttpServletRequest request) {
        IpInfo ipInfo = new IpInfo();
        String browser = request.getHeader("User-Agent");//浏览器信息
        String ip = request.getHeader("x-forwarded-for");//IP地址
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }
        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.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        ipInfo.setIp(ip);
        ipInfo.setUa(browser);
        ipInfo.setCity(new IpAddressService ().getCityName(ip));//根据IP地址获取城市
        return ipInfo;
    }

}

二、若使用IP地址获取城市,则创建 IpAddressService IP地址服务类

此类需用到IP地址库和jar包依赖

库的下载链接:【http://dev.maxmind.com/geoip/geoip2/geolite2/】或https://download.csdn.net/download/wzwsq/12798098

maven仓库地址:

<!--IP地址解析城市名依赖-->
<dependency>
    <groupId>com.maxmind.geoip2</groupId>
    <artifactId>geoip2</artifactId>
    <version>2.8.1</version>
</dependency>
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.net.InetAddress;

/**
 * IP与城市映射服务类
 **/
@Service
public class IpAddressService {
    private static Logger logger = LoggerFactory.getLogger(IpAddressService.class);

    private static String dbPath = "/data/ip/GeoLite2-City.mmdb";//服务器上存放GeoLite2-City.mmdb文件路径

    private static DatabaseReader reader;

    @Autowired
    private Environment env;

    @PostConstruct
    public void init() {
        try {
            String path = env.getProperty("geolite2.city.db.path");
            if (StringUtils.isNotBlank(path)) {
                dbPath = path;
            }
            File database = new File(dbPath);
            reader = new DatabaseReader.Builder(database).build();
        } catch (Exception e) {
            logger.error("IP地址服务初始化异常:" + e.getMessage(), e);
        }
    }


    //获取省份
    public String getSubdivision(String ipAddress){
        try {
            CityResponse response = reader.city(InetAddress.getByName(ipAddress));
            return response.getMostSpecificSubdivision().getNames().get("zh-CN");
        }catch (Exception e){
            logger.error("根据IP[{}]获取省份失败:{}", ipAddress, e.getMessage());
            return null;
        }
    }

    //获取市级
    public String getCityName(String ipAddress){
        try {
            CityResponse response = reader.city(InetAddress.getByName(ipAddress));
            return response.getCity().getNames().get("zh-CN");
        }catch (Exception e){
            logger.error("根据IP[{}]获取市級失败:{}", ipAddress, e.getMessage());
            return null;
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java ,可以使用正则表达式实现 URL 白名单过滤。具体步骤如下: 1. 定义白名单规则:使用正则表达式定义允许访问的 URL 规则。 例如,以下正则表达式匹配以 `https://www.example.com` 或 `http://www.example.com` 开头的 URL: ``` ^https?://www\.example\.com.* ``` 2. 使用白名单规则过滤 URL:对于每个请求的 URL,使用白名单规则进行匹配,如果 URL 符合规则,则允许访问,否则禁止访问。 例如,以下代码演示了如何使用正则表达式实现 URL 白名单过滤: ```java import java.util.regex.Pattern; public class UrlFilter { private final Pattern allowedPattern; public UrlFilter(String allowedRegex) { this.allowedPattern = Pattern.compile(allowedRegex); } public boolean isAllowed(String url) { return allowedPattern.matcher(url).matches(); } } ``` 在上面的代码,`UrlFilter` 类包含一个构造函数,用于传入白名单规则的正则表达式。`isAllowed` 方法用于判断 URL 是否允许访问,它使用 `Pattern` 类的 `matcher` 方法对 URL 进行匹配,返回匹配结果。 例如,以下代码演示了如何使用 `UrlFilter` 类进行 URL 过滤: ```java UrlFilter filter = new UrlFilter("^https?://www\\.example\\.com.*"); String url1 = "https://www.example.com/path/to/file.html"; String url2 = "http://www.example.com/index.html"; String url3 = "https://www.google.com/search?q=java"; System.out.println(filter.isAllowed(url1)); // true System.out.println(filter.isAllowed(url2)); // true System.out.println(filter.isAllowed(url3)); // false ``` 在上面的代码,我们先创建了一个 `UrlFilter` 对象,使用正则表达式 `^https?://www\\.example\\.com.*` 定义白名单规则。然后,我们分别对三个 URL 进行过滤,输出结果表明只有前两个 URL 符合白名单规则,最后一个 URL 不符合规则,被拒绝访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值