@WebFilter排除网址模式

我使用过滤器来检查登录用户的URL模式。

但是我有很多URL模式需要过滤。

{ "/table/*", "/user/*", "/contact/*", "/run/*", "/conf/*", ..., ..., ...}

它正在变得无法维护。仅排除以下内容会更简单:

{ "/", "/login", "/logout", "/register" }

我怎样才能做到这一点?

@WebFilter(urlPatterns = { "/table/*","/user/*", "/contact/*","/run/*","/conf/*"})
public class SessionTimeoutRedirect implements Filter {

    protected final Logger logger = LoggerFactory.getLogger("SessionFilter");

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        if (request.getSession().getAttribute("Id") != null) {
            chain.doFilter(req, res);
        } else {
            logger.debug("session is null:"+request.getRequestURL());                    
            response.sendRedirect(request.getContextPath()+"/login");
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

    @Override
    public void destroy() {

    }

}

答案 1

Servlet API 不支持“排除”URL 模式。

您最好的选择是将 HttpServletRequest#getRequestURI() 与允许的路径集进行比较。/*

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

    private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
        Arrays.asList("", "/login", "/logout", "/register")));

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", ""); 

        boolean loggedIn = (session != null && session.getAttribute("Id") != null);
        boolean allowedPath = ALLOWED_PATHS.contains(path);

        if (loggedIn || allowedPath) {
            chain.doFilter(req, res);
        }
        else {
            response.sendRedirect(request.getContextPath() + "/login");
        }
    }

    // ...
}

答案 2

您可以使用一些排除的模式并实现您的逻辑。这与BalusC的答案基本相同,只是通过使用它可以在Web中编写.xml如果需要/需要的话。initParaminitParam

下面我忽略了一些二进制(jpeg jpg png pdf)扩展名:

@WebFilter(urlPatterns = { "/*" },
    initParams = { @WebInitParam(name = "excludedExt", value = "jpeg jpg png pdf") }
)
public class GzipFilter implements Filter {

    private static final Set<String> excluded;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String excludedString = filterConfig.getInitParameter("excludedExt");
        if (excludedString != null) {
            excluded = Collections.unmodifiableSet(
                new HashSet<>(Arrays.asList(excludedString.split(" ", 0))));
        } else {
            excluded = Collections.<String>emptySet();
        }
    }

    boolean isExcluded(HttpServletRequest request) {
        String path = request.getRequestURI();
        String extension = path.substring(path.indexOf('.', path.lastIndexOf('/')) + 1).toLowerCase();
        return excluded.contains(extension);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.print("GzipFilter");
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        if (isExcluded(httpRequest)) {
            chain.doFilter(request, response);
            return;
        }

        // Do your stuff here
    }
}

推荐