Filter的功能是改变请求与响应
在一个请求到达Servlet 之前 处理request
在离开Servlet的时候处理 response
所以利用Filter可以检查request和response, 根据需要也可以修改request头 和 response头
对于spring boot, Filter配置可以使用原始的配置, 也可以使用新的配置方式
如下只以新的配置方式为例:
1. 创建一个类, 让它继承Filter
public class StealSource implements Filter {...}
2.在类上加@WebFilter注解, 并添加要过滤的请求地址
@WebFilter(urlPatterns="/*", filterName="handAll")
public class StealSource implements Filter {...}
3.在spring boot的启动器上添加注解, 将要用到的Filter加入进来
@SpringBootApplication // 这个与Filter无关(它只是标注此类为spring boot的启动器)
@ServletComponentScan(basePackageClasses=StealSource.class) // StealSource为要使用的Filter
public class App extends SpringBootServletInitializer {...}
经过上面简单的配置就可以正常使用了
网络上的资源, 有些我们拿来可以直接访问, 有些不能访问
<video src="xxx"/>
先打开一个网页, 然后找到原码(F12), 这里就可以看到xxx的具体内容是什么
当我们把这个xxx内容拷贝出来放入浏览器地址栏请求, 发现有些有效, 有些无效
经过测试和查找, 无效是由于链接防盗, 它设置了不能从外部域名进入到服务器
如下通过Filter简单设置防盗链接
原理: 请求的域名不等于服务器域名就不能通过
发送一个请求时, 如下:
地址为: https://mp.csdn.net/postedit
域名为: mp.csdn.net
使用request.getHeader("referer"); 获取地址
使用request.getServerName(); 获取域名
服务器域名不变, 关键就是看请求的地址中是否有服务器的域名
如果你是从地址输入的, 则后台服务器获取的地址为空
如果是从其它页面中请求的, 则域名不是服务器域名
如果是从服务器中的页面请求的, 则域名与服务器域名相同
实现代码:
@WebFilter(urlPatterns="/*", filterName="handAll")
public class StealSource implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter初始化...");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
/*禁用缓存*/
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragrma", "no-cache");
response.setDateHeader("Expires", 0);
/* 从请求头中获得的请求全地址*/
String referer = request.getHeader("referer");
// 如果为referer来源为null, 则表示直接从浏览器地地址输入的
if (referer == null) {
request.getRequestDispatcher("/index.html").forward(request, response);
return; // 不再向下执行
}
/* 发起请求域名或IP*/
String address = request.getServerName();
boolean contains = referer.contains(address);
/*如果不包含, 即发起请求的点不是本站的页面*/
if (!contains) {
request.getRequestDispatcher("/index.html").forward(request, response);
return;
}
// 放行
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("Filter销毁...");
}
}
最关键是要理解 request.getServletName()
获取的是网站的域名, 比如从index.html 的 a标签 发送的请求
后台使用request.getServletName() 获取到的就是index所属项目的域名
如果是本地创建一个html页面(不在项目中)来发送请求, 获取的就是localhost, 也就是本在ip
所以只能由项目所属页面发送的请求才能通过Filter, 从而达到 防盗 的目的