项目上有个小需求,要限制访问者的IP,屏蔽未授权的请求。该场景使用过滤器来做再合适不过了。
SecurityFilter.java:
public class SecurityFilter implementsFilter {private Log log = LogFactory.getLog(SecurityFilter.class);private List whitelist = new ArrayList();private List regexlist = new ArrayList();private static final String _JSON_CONTENT = "application/json; charset=UTF-8";private static final String _HTML_CONTENT = "text/html; charset=UTF-8";private static final String _403_JSON = "{'code': '403', 'msg': '访问被拒绝,客户端未授权!'}";private static final String _403_HTML = "
403 Forbidden!
@lichmama";@Overridepublic voiddestroy() {
}
@Overridepublic voiddoFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)throwsIOException, ServletException {
HttpServletRequest request=(HttpServletRequest) servletrequest;
HttpServletResponse response=(HttpServletResponse) servletresponse;if(isSecurityRequest(request)) {
filterchain.doFilter(request, response);
}else{
log.info("拒绝来自[" + request.getRemoteAddr() + "]的访问请求:" +request.getRequestURI());
response.setStatus(403);if(isAjaxRequest(request)) {
response.setContentType(_JSON_CONTENT);
response.getWriter().print(_403_JSON);
}else{
response.setContentType(_HTML_CONTENT);
response.getWriter().print(_403_HTML);
}
}
}
@Overridepublic void init(FilterConfig filterconfig) throwsServletException {
String allowedIP= filterconfig.getInitParameter("allowedIP");if (allowedIP != null && allowedIP.length() > 0) {for (String item : allowedIP.split(",\\s*")) {//支持通配符*
if (item.contains("*")) {
String regex= item.replace(".", "\\.").replace("*", "\\d{1,3}");
regexlist.add(regex);
}else{
whitelist.add(item);
}
}
}
}/*** 判断当前请求是否来自可信任的地址
*
*@paramrequest
*@return
*/
private booleanisSecurityRequest(HttpServletRequest request) {
String ip=request.getRemoteAddr();for(String item : whitelist) {if(ip.equals(item))return true;
}for(String item : regexlist) {if(ip.matches(item))return true;
}return false;
}/*** 判断请求是否是AJAX请求
*@paramrequest
*@return
*/
private booleanisAjaxRequest(HttpServletRequest request) {
String header= request.getHeader("X-Requested-With");if (header != null && header.length() > 0) {if ("XMLHttpRequest".equalsIgnoreCase(header))return true;
}return false;
}
}
web.xml增加配置:
securityFilter
com.lichmama.webdemo.filter.SecurityFilter
allowedIP
192.168.5.*
securityFilter
/*
尝试访问,结果如下:
*如何在Filter中获取Response的内容?这个问题之前还真没思考过,搜索了下得知如下方法可行:
1.实现一个PrintWriterWrapper,用于替换ServletResponse中的Writer
packagecom.lichmama.webdemo;importjava.io.PrintWriter;importjava.io.Writer;public class PrintWriterWrapper extendsPrintWriter {privateStringBuilder buff;publicPrintWriterWrapper(Writer writer) {super(writer);
buff= newStringBuilder();
}
@Overridepublic void write(inti) {super.write(i);
buff.append(i);
}
@Overridepublic void write(char[] ac, int i, intj) {super.write(ac, i, j);
buff.append(ac, i, j);
}
@Overridepublic void write(char[] ac) {super.write(ac);
buff.append(ac);
}
@Overridepublic void write(String s, int i, intj) {super.write(s, i, j);
buff.append(s, i, j);
}
@Overridepublic voidwrite(String s) {super.write(s);
buff.append(s);
}
@Overridepublic voidflush() {super.flush();
buff.delete(0, buff.length());
}publicString getContent() {returnbuff.toString();
}
}
View Code
2.实现一个ResponseWrapper,用于替换过滤链(FilterChain)中的ServletResponse:
packagecom.lichmama.webdemo;importjava.io.IOException;importjava.io.PrintWriter;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpServletResponseWrapper;public class ResponseWrapper extendsHttpServletResponseWrapper {privatePrintWriterWrapper writer;publicResponseWrapper(HttpServletResponse response) {super(response);
}
@Overridepublic PrintWriter getWriter() throwsIOException {if (writer == null)
writer= new PrintWriterWrapper(super.getWriter());returnwriter;
}
}
View Code
3.编写Filter实现获取Response的内容捕获:
packagecom.lichmama.webdemo.filter;importjava.io.IOException;importjavax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.http.HttpServletResponse;importcom.lichmama.webdemo.PrintWriterWrapper;importcom.lichmama.webdemo.ResponseWrapper;public class TestFilter implementsFilter {
@Overridepublic void init(FilterConfig filterconfig) throwsServletException {
}
@Overridepublic voiddoFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)throwsIOException, ServletException {
ResponseWrapper responsewrapper= newResponseWrapper((HttpServletResponse) servletresponse);
filterchain.doFilter(servletrequest, responsewrapper);
PrintWriterWrapper writerWrapper=(PrintWriterWrapper) responsewrapper.getWriter();//TODO retrieve content from PrintWriterWrapper
String content =writerWrapper.getContent();
}
@Overridepublic voiddestroy() {
}
}
that's it~