设置站点黑名单的过滤器(BannedAccessFilter)
本系列文章导读:
设置站点黑名单的过滤器(BannedAccessFilter)
将响应数据进行压缩处理的过滤器(CompressionFilter)
替换禁用语(指定关键字)的过滤器(StopWordsFilter)
功能描述
不允许从禁用的站点(IP)访问当前应用,也不允许从禁用的站点链接到当前应用。
为了简单起见,设置禁用站点时,暂不支持使用通配符。只是抛砖引玉了。
比如:禁止其他的网站引用本站的图片资源,只需在此基础上稍作修改即可。
使用方法
在 java web 项目的 web.xml 文件中添加如下代码。
<!--设置站点黑名单的过滤器配置 开始 --> <filter> <filter-name>BannedAccessFilter</filter-name> <filter-class>com.hmw.filter.BannedAccessFilter</filter-class> <init-param> <description>需要禁用的站点,一个站点占用一行</description> <param-name>bannedSites</param-name> <param-value> 192.168.1.101 192.168.1.102 www.csdn.net </param-value> </init-param> </filter> <filter-mapping> <filter-name>BannedAccessFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--设置站点黑名单的过滤器配置 结束 -->
过滤器源码
package com.hmw.filter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.StringTokenizer;
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.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
/**
* 设置禁用站点(黑名单)的过滤器
* @author 何明旺
*/
public class BannedAccessFilter implements Filter {
static final Logger logger = Logger.getLogger(BannedAccessFilter.class);
private HashSet bannedSiteTable;
/**
* 将配置的禁用站点列表初始化到一个 HashSet 中
*/
@Override
public void init(FilterConfig config) throws ServletException {
bannedSiteTable = new HashSet();
String bannedSites = config.getInitParameter("bannedSites");
// Default token set: white space.
StringTokenizer tok = new StringTokenizer(bannedSites);
while (tok.hasMoreTokens()) {
String bannedSite = tok.nextToken();
bannedSiteTable.add(bannedSite);
logger.info("Banned " + bannedSite);
}
}
/**
* 如果请求来自被禁用的站点,或是从被禁用的站点链接过来的,则拒绝访问。
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
logger.debug("BannedAccessFilter: Filtering the Request...");
HttpServletRequest req = (HttpServletRequest) request;
String requestingHost = req.getRemoteHost();
String referringHost = getReferringHost(req.getHeader("Referer"));
String bannedSite = null;
boolean isBanned = false;
if (bannedSiteTable.contains(requestingHost)) {
bannedSite = requestingHost;
isBanned = true;
} else if (bannedSiteTable.contains(referringHost)) {
bannedSite = referringHost;
isBanned = true;
}
if (isBanned) {
showWarning(response, bannedSite);
} else {
chain.doFilter(request, response);
}
logger.debug("BannedAccessFilter: Filtering the Response...");
}
@Override
public void destroy() {
}
/**
* 根据 URL 链接地址,取得该链接地址所在的站点
* @param refererringURLString URL链接地址
* @return 该 URL 链接地址所在的站点,如果传入的参数不是一个符合URL规范的字符串,则返回 null
*/
private String getReferringHost(String refererringURLString) {
if(StringUtils.isBlank(refererringURLString))
return null;
try {
URL referringURL = new URL(refererringURLString);
return referringURL.getHost();
} catch (MalformedURLException mue) { // Malformed
return null;
}
}
/**
* 如果用户是从禁用站点访问的该应用,或是从禁用站点链接过来的,则调用此方法将警告信息展现给用户。
* @param response HTTP请求响应对象
* @param bannedSite 禁止的站点
* @throws ServletException
* @throws IOException
* @author 何明旺
*/
private void showWarning(ServletResponse response, String bannedSite) throws ServletException, IOException {
String htmlCode = "";
htmlCode += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
htmlCode += "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
htmlCode += " <head>";
htmlCode += " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
htmlCode += " <title>禁止访问</title>";
htmlCode += " </head>";
htmlCode += " <body>";
htmlCode += " <h1>禁止访问</h1>";
htmlCode += " <p>对不起,您无法访问该资源,因为您的站点已经被列入我们的黑名单!</p>";
htmlCode += " <p>您的站点是:<strong>" + bannedSite + "</strong></p>";
htmlCode += " </body>";
htmlCode += "</html>";
response.setContentType("text/html");
PrintWriter out = null;
try{
out = response.getWriter();
out.println(htmlCode);
}finally{
if(out != null){
out.flush();
out.close();
}
}
/*
* 也可以使用下面的方法直接转发或重定向到指定的警告页面
* 转发:
* ((HttpServletRequest)request).getRequestDispatcher("/warn.html").forward(request, response);
* 重定向:
* ((HttpServletResponse)response).sendRedirect("webAppContext/warn.html");
*/
}
}