作用
拦截请求,过滤响应
实现
实现 Filter 接口
执行顺序
根据过滤器的配置方式分别
-
配置文件(web.xml)配置,执行顺序由
<filter-mapping>
标签的配置顺序决定 -
注解配置,执行顺序由filterName属性值的字母顺序决定
常见问题
无法实现Filter接口
找到apache-tomcat-8.5.75->lib->Servlet-api.jar导入
字符编码设置
@WebFilter(urlPatterns = {"/*"})
public class CharsetFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html;charset=UTF-8");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
web.xml配置Filter
<!--配置过滤器-->
<filter>
<filter-name>Charser</filter-name>
<filter-class>com.xxx.controller.filter.CharsetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Charser</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
敏感词汇过滤(没怎么搞懂流程)
@WebFilter(urlPatterns = {"*.do"})
public class BanFilter implements Filter {
// 存放违规字符的集合
private List<String> words = new ArrayList<>();
// 加载时读取文件字符存入集合
@Override
public void init(FilterConfig filterConfig) throws ServletException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Knowledge\\编程\\00-资料库\\05-File\\words.txt"), "utf-8"))) {
String str = null;
while ((str = reader.readLine()) != null) {
words.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 过滤违规字符
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String text = servletRequest.getParameter("text");
// 创建请求对象的代理对象,
// 在代理对象的方法执行过程中判断当前方法是不是getParameter
// 是则获取值进行相应修改
// 最后将代理传递给servlet
ServletRequest requestProxy = (ServletRequest) Proxy.newProxyInstance(servletRequest.getClass().getClassLoader(),
servletRequest.getClass().getInterfaces(), new InvocationHandler() {
// method:真实对象调用某个方法的方法对象
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用真实对象方法
Object returnValue = method.invoke(servletRequest, args);
// 获取真实对象调用的方法的方法名
String methodName = method.getName();
if (methodName.equals("getParameter")) {
String value = (String) returnValue;
for (String word : words) {
if (value.contains(word)) {
value = value.replace(word, "*");
}
}
return value;
}
return returnValue;
}
});
// 放行时传递的是代理对象
filterChain.doFilter(requestProxy,servletResponse);
}
@Override
public void destroy() {
}
}
登录校验
基于会话完成登录状态的保存,向系统中发送请求时,通过过滤器拦截请求,验证会话中是否存储了登录状态,如果有,则放行,如果没有,则重定向到登录页面(登录成功必须向会话对象中保存登录状态)
校验特定资源
重点在登录校验过滤器的url-pattern的配置上
// 对特定资源进行登录校验
@WebFilter(urlPatterns = "*.do")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
// 获取Session值
Object loginUser = req.getSession().getAttribute("user");
// 未登录状态
if (null == loginUser) {
// 跳转回主页面
resp.sendRedirect("/html/main.html");
// 登录状态
} else {
// 放行
filterChain.doFilter(req, resp);
}
}
@Override
public void destroy() {}
}
校验所有资源
重点在需要放行的资源上
// 对所有资源进行登录校验
@WebFilter(urlPatterns = {"/*"})
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
// 在该方法内部完成登录校验
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
// 获取请求地址,如:@WebServlet("/test.do") == /test.do
String requestURI = req.getRequestURI();
if (requestURI.endsWith("login.jsp")
|| requestURI.endsWith("register.jsp")
|| requestURI.endsWith("login.do")
|| requestURI.endsWith("register.do")
) {
//请求特定资源放行
filterChain.doFilter(req,resp);
//其它所有的请求和页面都必须进行登录校验
}else{
Object loginUser = req.getSession().getAttribute("User");
//没有登录:打回
if (null == loginUser) {
resp.sendRedirect("/html/login.html");
//登录过了:放行
}else{
filterChain.doFilter(req,resp);
}
}
}
@Override
public void destroy() {}
}