将 shiro 与码头集成时出现 UnavailableSecurityManagerException

UnavailableSecurityManagerException while integrating shiro with jetty

我正在尝试将 Shiro 与我们的“遗留”Client/Server 应用程序(Java 8、Jetty 9、Shiro 1.9)集成。我遵循了 https://shiro.apache.org/web.html 上的文档并尝试使其适应我们现有的代码,但是当我尝试访问 SecurityManager.

时我得到了一个 UnavailableSecurityManagerException

我设置了一个 ServletContextHandler 并试图将它与我们现有的请求处理程序 (AbstractHandler) 结合起来。有趣的是,我可以使用安全管理器实例访问上下文(即使用 request.getServletContext().getAttribute("org.apache.shiro.web.env.EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY")),但它不会被 shiro 处理。

我可以使用 SecurityUtils 手动设置安全管理器,但这不是我想要的,因为我想要基于请求的安全性。此外,会话 cookie 根本没有设置和处理。

这是我的代码的(精简)版本:

/* Context */

public class SecurityContext extends ServletContextHandler {
    SecurityContext(String configLocations) {
        super();
        EnvironmentLoaderListener listener = new EnvironmentLoaderListener();
        //this.setInitParameter("shiroEnvironmentClass", "org.apache.shiro.web.env.IniWebEnvironment");
        this.addFilter("org.apache.shiro.web.servlet.ShiroFilter", "/*", EnumSet.allOf(DispatcherType.class));
        this.setInitParameter("shiroConfigLocations", configLocations);
        this.addEventListener(listener);
    }
}
/* Request Handler */

public final class RequestHandler extends AbstractHandler {
    public void handle(final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
        Subject subject = SecurityUtils.getSubject(); // throws UnavailableSecurityManagerException!
        HandlerResult handlerResult = JsonResult.notFound(this.gson);
        // ...
        handlerResult.writeTo(response);
        baseRequest.setHandled(true);
    }
}

/* Web Server: */

protected void startUp() throws Exception {
        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStore(SSLKeyStore.create("server.keystore"));
        sslContextFactory.setKeyStorePassword(SSLKeyStore.KEYSTORE_PASSWORD);
        sslContextFactory.setProtocol("TLSv1.2");

        SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, "http/1.1");
        HttpConnectionFactory http = new HttpConnectionFactory(new HttpConfiguration());


        /* connectors */
        ServerConnector sslConnector = new ServerConnector(this.server, ssl, http);
        sslConnector.setPort(this.port);
        this.server.addConnector(sslConnector);

        /* handlers */
        GzipHandler gzip = new GzipHandler();
        gzip.setIncludedMimeTypes("text/html", "text/plain", "application/json");

        RequestHandler requestHandler = new RequestHandler();

        SecurityContext context = new SecurityContext("classpath:shiro.ini");
        context.setGzipHandler(gzip);
        context.insertHandler(new HandlerWrapper() {
            @Override
            public void handle(final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
                SecurityUtils.getSubject(); // throws UnavailableSecurityManagerException!
                requestHandler.handle(target, baseRequest, request, response);
            }
        });

        server.setHandler(context);

        this.server.start();
    }

我发现 ShiroFilter 没有被请求触发。我更改了我的请求处理程序以扩展 javax.servlet.http.HttpServlet,现在可以使用了!