缘起
首先,用查抄Referer的方法来防披御CSRF并不是很好的要领。因项目姑且有需要,所以做为过渡方案。
为什么判定referer不是很好的步伐?
https跳转http没有referer
https跳转差异的域名的https没有referer
通过非凡结构的POST请求没有referer
一些的proxy会把referer去掉
用户直接在欣赏器里会见(GET请求)
结构空referer请求的一些参考资料
防止CSRF今朝较量好的步伐是CSRF Token,参考另一篇blog:Cookie & Session & CSRF。
##收集资料
先搜索下前人有没有这类相关的事情。
搜索到的关于RefererFilter的信息并不多。
不外这里学到了一些东东:
https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.security-1.0.0/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
再搜索下java里提取request的referer的要领,尚有filter里重定向请求的要领。
再仔细看了下OWASP的文档:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
##确定方案
为什么不消正则的方法来处理惩罚referer?
##思考需要提供的设置项
实际最终提供了这些设置项,思量到像host这样的设置不是常常变换的,所以没有提供从外部设置文件加载设置的成果。
matchMethods 即拦截的要领,默认值"POST|PUT|DELETE|CONNECT|PATCH",凡是不消设置 allowSubDomainHosts 匹配子域名,以"|"脱离,如"test.com|abc.com", 则http://test.com, http://xxx.test.com这样的请求城市匹配到,推荐优先利用这个设置 completeMatchHosts 完全匹配的域名,以"|"脱离,如"test.com|abc.com",则只有http://test.com 这样的请求会匹配 像http://www.test.com 这样的请求不会被匹配 responseError 被拦截的请求的response的返回值,默认是403 redirectPath 被拦截的请求重定向到的url,假如设置了这个值,则会忽略responseError的设置。 好比可以设置重定向到本身界说的错误页: /referer_error.html bAllowEmptyReferer 是否答允空referer,默认是false,除非很清楚,不然不要窜改这个 bAllowLocalhost 是否答允localhost, 127.0.0.1 这样的referer的请求,默认是true,便于调试 bAllowAllIPAndHost 是否答允本机的所有IP和host的referer请求,默认是false
##编码的细节
response.sendRedirect(request.getContextPath() + redirectPath);
##正确地处理惩罚URL
感受这个有须要再次说明下:
http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html
用contain, indexOf, endWitch这些函数时都要小心。
public static void main(String[] args) throws Exception { URL aURL = new URL("http://example.com:80/docs/books/tutorial" + "/index.html?name=networking#DOWNLOADING"); System.out.println("protocol = " + aURL.getProtocol()); System.out.println("authority = " + aURL.getAuthority()); System.out.println("host = " + aURL.getHost()); System.out.println("port = " + aURL.getPort()); System.out.println("path = " + aURL.getPath()); System.out.println("query = " + aURL.getQuery()); System.out.println("filename = " + aURL.getFile()); System.out.println("ref = " + aURL.getRef()); }
##用curl来测试
最后用curl来做了一些测试:
curl --header "Referer:http://test.com" http://localhost:8080/filter-test/referer curl -X POST --header "Referer:http://test.com" http://localhost:8080/filter-test/referer curl -X POST --header "Referer:xxxxx" http://localhost:8080/filter-test/referer curl -X POST http://localhost:8080/filter-test/referer curl -X POST --header "Referer:http://abc.test.com" http://localhost:8080/filter-test/referer curl -X POST --header "Referer:http://abc.hello.com.test.com" http://localhost:8080/filter-test/referer