如何使用Spring MVC创建自己的过滤器?

2022-09-01 10:31:59

我使用Spring MVC(4.0.1)作为休息服务的后端,并使用angularjs作为前端。

对我的服务器后端的每个请求都有一个带有会话ID的http标头

我可以使用以下代码在服务器后端读取此标头:

@Autowired
protected HttpServletRequest request;
String xHeader=request.getHeader("X-Auth-Token"); //returns the sessionID from the header

现在我调用此方法,它只返回 true 或 false。如果用户存在于我的数据库中,它将返回 true 否则返回 false!getPermission(xHeader)

我现在想要创建一个具有此行为的过滤器,该过滤器检查每个请求,如果用户有权访问我的控制器!但是,如果该方法返回 false,它应该发回 401 错误,而不是到达我的控制器!

如何执行此操作并创建自己的筛选器?我只使用Java Config,不使用XML。

我想我必须在这里添加过滤器:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Filter[] getServletFilters() {
        MyOwnFilter=new MyOwnFilter();
        return new Filter[] {MyOwnFilter};
    }
}

答案 1

作为过滤器的替代方案,您可以使用 HandlerInterceptor

public class SessionManager implements HandlerInterceptor{

    // This method is called before the controller
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        String xHeader = request.getHeader("X-Auth-Token");
        boolean permission = getPermission(xHeader);
        if(permission) {
            return true;
        }
        else {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
            // Above code will send a 401 with no response body.
            // If you need a 401 view, do a redirect instead of
            // returning false.
            // response.sendRedirect("/401"); // assuming you have a handler mapping for 401

        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }
}

然后将此拦截器添加到您的webmvc配置中。

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    SessionManager getSessionManager() {
         return new SessionManager();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getSessionManager())
        .addPathPatterns("/**")
        .excludePathPatterns("/resources/**", "/login");
     // assuming you put your serve your static files with /resources/ mapping
     // and the pre login page is served with /login mapping
    }

}

答案 2

下面是执行您提到的逻辑的过滤器

@WebFilter("/*")
public class AuthTokenFilter implements Filter {

    @Override
    public void destroy() {
        // ...
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String xHeader = ((HttpServletRequest)request).getHeader("X-Auth-Token");
        if(getPermission(xHeader)) {
            chain.doFilter(request, response);
        } else {
            request.getRequestDispatcher("401.html").forward(request, response);
        }
    }
}

你做对了,弹簧配置应该遵循。

public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new AuthTokenFilter()};
    }
}

推荐