步骤解析
登录过滤器场景
:在web开发中,存在一个问题,当用户登录后才能进行后面的操作。如果用户没有登陆那么后面的所有url请求都必须要拦截。
类似于这种拦截
的场景,就适合使用过滤器的方式来进行实现,还有适合使用的场景有:登录权限验证、资源访问权限控制、敏感词汇过滤、字符编码转换…
以登录过滤器场景
,本文收集了SSM/SpringBoot中过滤器如何使用或如何编写。作为一个学习总结,也便于日后查找。
核心就是构造一个类,实现Filter接口,重写doFilter方法
- 先定义一个数组,存放要放行的url。
// 定义要放行的url数组
private String[] urls = {
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
- SSM/SpringBoot项目中,采用
@WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*")
注解来表明该类是一个过滤器。作用相当于在web.xml中配置过滤器。- filterName: 过滤器名称
- urlPatterns: 过滤器要过滤的uri,支持通配符。
org.springframework.util.AntPathMatcher
该类可以用来路径匹配,并支持通配符
// 路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
/**
* 判断路径是否被拦截
* @param requestURI
* @return
*/
public boolean check(String requestURI){
for(String uri : urls){
boolean match = PATH_MATCHER.match(uri, requestURI);
if(match){
return true;
}
}
return false;
}
filterChain.doFilter(request,response);
用来放行操作。
完整代码
package com.lz.gyh.filter;
import com.alibaba.fastjson.JSON;
import com.lz.gyh.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否完成登录过滤器
*/
@WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
// 路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
// 定义要放行的url数组
private String[] urls = {
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
// 1. 先获取请求的URI
String requestURI = request.getRequestURI();
// 2. 判断本次请求是否需要处理
boolean flag = check(requestURI);
// 3. 如果不需要处理,则直接放行
if(flag){
filterChain.doFilter(request,response);
return;
}
// 4. 判断登录状态,如果已经登陆,则直接放行
/*
是否登录用Session存储具体的id来进行实现,
如果说这里session为null,则表明没有登陆成功
这里if条件代码需要替换为具体的判断逻辑
*/
if(request.getSession().getAttribute("employee") != null){
filterChain.doFilter(request,response);
return;
}
// 5. 如果未登录则返回未登录结果,并通过输出流的方式向客户端返回响应数据
/*
R类为我做的一个结果类,这里可以替换为具体的情况。
*/
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
}
/**
* 判断路径是否被拦截
* @param requestURI
* @return
*/
public boolean check(String requestURI){
for(String uri : urls){
boolean match = PATH_MATCHER.match(uri, requestURI);
if(match){
return true;
}
}
return false;
}
}
附录
- R结果类:
package com.lz.gyh.common;
import java.util.HashMap;
import java.util.Map;
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}