一:过滤器实现
代码不用多说 B站课程有详解,老师用的就是这个 代码如下:
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter{
//路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@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();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
/**
* 路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}
return false;
}
}
二:拦截器实现
首先自己写一个拦截器类 LoginHandlerInterceptor,去实现HandlerInterceptor这个接口,然后重写里面的preHandle方法。
我的代码如下:
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object employee = request.getSession().getAttribute("employee");
if(employee != null) {
return true;
}else {
System.out.println("saaaaaas");
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
//response.sendRedirect("/backend/page/login/login.html");
System.out.println("拦截到请求:"+request.getRequestURI());
return false;
}
}
}
然后去自己的WebMvcConfig类中注册这个拦截器类LoginHandlerInterceptor
代码如下:
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/employee/login",
"/employee/logout","/backend/**","/front/**");
}
测试后:效果和老师的一样,未登录访问首页后会先看到首页然后跳转到登录页.
但是访问不存在的地址会返回一个json字符串(这是符合逻辑的,这个json数据没被转化可能时前端vue的一些问题,暂时不太清楚原理)如下图所示
检查控制台发现下图
这个请求时404为啥不显示404错误的界面而是把json字符串显示出来,不清楚原因 .
*上面的做法感觉欠妥,拦截后应该是看不到界面,而是直接跳转到登录界面,可以用重定向的方式实现
三:拦截器重定向实现
需改动代码如下:
拦截路劲也需要改动
测试结果:未登录状态下无论输入地址(除了登录页)都会重定向登录页
这种方法有一个bug:
但我们登录后退出来的时输入/backend/index.html这个地址会直接显示首页,检查发现下图
这个可能是缓冲造成的
这种情况下再输入/backend/index.html会正常的重定向到首页
此时的请求为正常的重定向
具体原因未知:
自己写的都有漏洞,知识有限,无法解决