【问题标题】:How can I disable authentication for a specific servlet/pathSpec?如何禁用特定 servlet/pathSpec 的身份验证?
【发布时间】:2025-12-08 06:10:01
【问题描述】:

我的代码如下(引用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 路径的东西。

【问题讨论】:

    标签: java servlets jetty forms-authentication jetty-9


    【解决方案1】:
    ConstraintMapping constraintMapping = new ConstraintMapping();
    constraintMapping.setConstraint(constraint);
    constraintMapping.setPathSpec("/*");
    

    不幸的是,服务器约束映射没有“排除”的概念。

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

    【讨论】:

    • 我最终在根路径中放置了一个页面,该页面重定向到具有约束的路径。这样我就可以使 /metrics 页面不受它的影响。我希望有一种更清洁的方法来做到这一点。