代码之家  ›  专栏  ›  技术社区  ›  Web User

过滤器(在springbootwebapp中)可以基于所有定义的请求映射来验证请求URL吗?

  •  0
  • Web User  · 技术社区  · 7 年前

    我在一个SpringBootWeb应用程序中实现了一个过滤器(用 @Component @Order(Ordered.HIGHEST_PRECEDENCE)

    但是我想在执行任何其他验证(如cert验证)之前验证URL,这样我就可以立即指出它是否是404。因为我遇到了一个很有必要的案子。

    更新日期:2018年9月23日

    AuthFilter.java

    @Component
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class AuthFilter implements Filter {
    
        private final Logger logger = LoggerFactory.getLogger(AuthFilter.class);
    
        // Define paths that require only client certificate but no Authorization token
        private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(
                new HashSet<>(
                        Arrays.asList("/login", "/register", "/error" )));
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            logger.debug("Initiating AuthFilter...");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
    
            if (!(request instanceof HttpServletRequest)) {
                return;
            }
    
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            String path = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()).replaceAll("[/]+$", StringUtils.EMPTY);
            logger.debug("AuthFilter intercepting request: {}", path);
            boolean allowedPath = ALLOWED_PATHS.contains(path);
    
            int responseCode = 400;
            String responseException = null;
    
            if (allowedPath) {
    
                if (this.checkClientCert(CLIENT_CERT_NAME, httpRequest)) {
                    logger.debug("{} cert is valid, moving request along", CLIENT_CERT_NAME);
                    chain.doFilter(request, response);
                    return;
                }
    
                responseCode = 403;
                responseException = new AuthException("certificate missing", "Must provide a valid client certificate");
                sendResponse(responseCode, responseException, httpResponse);
                return;
            }
    
            try {
    
                logger.debug("Checking {} cert and authorization token...", CLIENT_CERT_NAME);
                boolean validClientCert = this.checkClientCert(CLIENT_CERT_NAME, httpRequest);
                boolean validAuthToken = this.checkAuthToken(httpRequest.getHeader("Authorization"));
                if (validClientCert && validAuthToken) {
                    logger.debug("{} cert and Auth token are good!", CLIENT_CERT_NAME);
                    chain.doFilter(request, response);
                    return;
                }
            } catch (Exception e) {
                responseCode = 403;
                responseException = new AuthException("certificate or auth token is missing or invalid", "Must provide a valid client certificate and auth token");
                sendResponse(responseCode, responseException, httpResponse);
            }
        }
    
        @Override
        public void destroy() {
            throw new UnsupportedOperationException();
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   Huy Nguyen    7 年前

    我认为您可能误解或误解了javaservlet过滤器和spring组件。

    但您的问题可以通过以下两种方式解决:

        2
  •  0
  •   Mark Bramnik    7 年前

    springmvc是围绕一个特定的servlet构建的,该servlet具有内部调度功能,基于Spring控制器配置。一旦请求到达集中式调度器,它将检查映射并将呼叫路由到特定的控制器。如果没有映射,则抛出异常。作为servlet规范的一部分,Filter太“低级”,它只能捕捉到对springmvc的“一般”请求,因此您将无法使它与过滤器抽象一起工作,因为它与springmvc端点的内部路由无关。

    但是,您可以使用拦截器,spring特有的方式来拦截对某些控制器的调用。拦截器的代码将完成基于证书的工作。

    在这种情况下,URL映射将由springmvc框架自动检查。

    您可以找到有关使用这些拦截器的教程 Here

    另一个可能的解决方案(虽然与您的问题没有直接关系)是使用springsecurity,从这个问题来看,它似乎是处理证书的正确抽象,但这只是一个附带说明