如何禁用特定 servlet/pathSpec 的身份验证?

How can I disable authentication for a specific servlet/pathSpec?

我的代码如下(参考Embedded Jetty - Programatically add form based authentication):

    ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);

    context.addServlet(new ServletHolder(new DefaultServlet() {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.getWriter().append("Hello " + request.getUserPrincipal().getName());
        }
    }), "/*");

    context.addServlet(new ServletHolder(new DefaultServlet() {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.getWriter().append("<html><form method='POST' action='/j_security_check'>"
                    + "<input type='text' name='j_username'/>"
                    + "<input type='password' name='j_password'/>"
                    + "<input type='submit' value='Login'/></form></html>");
        }
    }), "/login");

    context.addServlet(new ServletHolder(new DefaultServlet(){
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.getWriter().append("This is the metrics page!");
        }
    }), "/metrics");

    Constraint constraint = new Constraint();
    constraint.setName(Constraint.__FORM_AUTH);
    constraint.setRoles(new String[]{"admin"});
    constraint.setAuthenticate(true);

    ConstraintMapping constraintMapping = new ConstraintMapping();
    constraintMapping.setConstraint(constraint);
    constraintMapping.setPathSpec("/*");

    ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
    securityHandler.addConstraintMapping(constraintMapping);
    TestingLoginService loginService = new TestingLoginService();
    securityHandler.setLoginService(loginService);

    FormAuthenticator authenticator = new FormAuthenticator("/login", "/login", false);
    securityHandler.setAuthenticator(authenticator);

    context.setSecurityHandler(securityHandler);

这可行,但我希望 /metrics servlet 不要求对用户进行身份验证。但是,我仍然希望所有其他路径都转到登录名和 "Hello" servlet。

我能想到的唯一其他解决方案是将 "Hello" servlet 移动到不同的路径,并让根路径重定向到该路径。这样我就可以将 ConstraintMapping 的 pathSpec 设置为不包含 /metrics 路径的东西。

ConstraintMapping constraintMapping = new ConstraintMapping();
constraintMapping.setConstraint(constraint);
constraintMapping.setPathSpec("/*");

不幸的是,服务器约束映射没有 "exclude" 的概念。

您必须添加涵盖所需内容的多个路径规范,只是不在该路径规范列表中包含 /metrics 路径规范。