SprinBoot——WebMvcConfigurer的excludePathPatterns配置 "失效" 问题


作者:空白

1. 问题描述

SpringMvc的WebMvcConfigurerexcludePathPatterns配置的路径不拦截“失效“

设置路径不被拦截

/**
 * 登录检验拦截
 * @author YI
 * @date 2018-7-19 14:55:13
 */
@Configuration
public class WebSecurityConfig implements WebMvcConfigurer {

    @Bean
    public JdkApiInterceptor JdkApiInterceptor(){
        return new JdkApiInterceptor();
    }

    /**
     * 拦截器注册 设置拦截接口
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	
        registry.addInterceptor(JdkApiInterceptor()).addPathPatterns("/**")//设置拦截所有的路径
        		//排除的路径:静态资源路径。防止被JdkApiInterceptor拦截
                .excludePathPatterns("/loginCheck","/login",
                        "/js/**", "/css/**", "/imag/**");
    }

拦截器 所有未配置不拦截的路径 都会被这个拦截器拦截,不满足条件就会重定向到login页面。

package org.jackdking.login.jwt.inteceptor;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jackdking.login.jwt.utils.CookieUtil;
import org.jackdking.login.jwt.utils.RedisOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class JdkApiInterceptor implements HandlerInterceptor {
	
	
    private static final Logger logger = LoggerFactory.getLogger(JdkApiInterceptor.class);
    
    
    public static final String USER_REDIS_SESSION = "user_redis_session";

    @Autowired
    public RedisOperator redis;

    /**
     * 拦截请求,在controller调用之前
     * 返回 false:请求被拦截,返回
     * 返回 true :请求OK,可以继续执行,放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
        String userToken = CookieUtil.getCookie("userToken");//获取用户cookies
        String userName = CookieUtil.getCookie("userName");
        
//        //放开登入接口
//        String uri = request.getRequestURI();
//        logger.info("请求uri:" + uri);
//        
//        if(uri.equals("loginCheck"))
//        	return true;
//        
        logger.info("拦截UserToken:" + userToken + " ======= 拦截UserId:" + userName);
        //用户id和token都不为空
        if (!StringUtils.isEmpty(userName) && !StringUtils.isEmpty(userToken)) {
        	
        	//根据userid生成唯一key从redis中查出唯一token
            String uniqueToken = redis.get(USER_REDIS_SESSION + ":" + userName);
            logger.info("拦截uniqueToken:" + uniqueToken);
            
            //如果唯一token为空 ,则拦截url重定向到登入页面
            if (!StringUtils.isEmpty(uniqueToken) && !StringUtils.isEmpty(uniqueToken)) {
                response.sendRedirect("/login");
                returnErrorResponse(response, "请登录...");

                return false;
            }
        //用户id和token有一个为空,则重定向登入页面
        } else {
            response.sendRedirect("/login");
            returnErrorResponse(response,"请登录...");
            return false;
        }

        return true;
    }

    /**
     * 把拦截数据返回给前端
     * @param response
     * @param result
     * @throws IOException
     */
    private void returnErrorResponse(HttpServletResponse response, String result) throws IOException {
        response.setContentType("text/json");
        response.setCharacterEncoding("utf-8");
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            out.write(result.getBytes("utf-8"));
            out.flush();
        } finally {
            if(out!=null){
                out.close();
            }
        }
    }

    /**
     * 请求controller之后,渲染视图之前
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {

    }

    /**
     * 请求controller之后,视图渲染之后
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {

    }
}

测试loginCheck接口:http://localhost:8080/loginCheck 发现 访问该接口后 返回的是登入页面 因此“认定“(其实是错误的)被拦截了

alt

2. 发现问题

在拦截器中打印 每次拦截的url路径

        //放开登入接口
        String uri = request.getRequestURI();
        logger.info("请求uri:" + uri);
        
        if(uri.equals("loginCheck"))
        	return true;

然后再次访问loginCheck接口,日志结果如下

2020-09-30 11:25:20.933  INFO 5808 --- [nio-8080-exec-2] o.j.l.jwt.inteceptor.JdkApiInterceptor   : 请求uri:/error

loginCheck接口确实没有被拦截,但是多了个 /error接口。查阅资料发线,springboot接口中默认的拦截器 会拦截接口错误并重定向到/error接口。

因此 我们配置的 /loginCheck接口确实是成功放行了。

3. 解决问题

这里就不要再拦截 /error借口了,因此要将/error放入到不拦截配置中,重新访问后返回结果如下: postman返回结果

{
    "timestamp": 1601436537651,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
    "message": "Required String parameter 'username' is not present",
    "path": "/loginCheck"
}

关注共图社,有更多惊喜。


转载这篇文章需要标注作者和出处:空白-bittechblog

alt

扫码或搜索:前沿科技
发送 290992
即可立即永久解锁本站全部文章