I'm trying to integrate Shiro with our "legacy" Client/Server application (Java 8, Jetty 9, Shiro 1.9). I followed the Documentation on https://shiro.apache.org/web.html and tried to adapt it to our existing code, but I get an UnavailableSecurityManagerException
when I try to access the SecurityManager
.
I set up a ServletContextHandler
and tried to combine it with our existing request handler (AbstractHandler
). The funny thing is, I can access the context with the Security Manager instance (i.e., with request.getServletContext().getAttribute("org.apache.shiro.web.env.EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY")
), but it doesn't get handled by shiro.
I could set the security manager manually with SecurityUtils, but that's not what I want as I want request based security. Also, the session cookies are not set and processed at all.
Here's a (stripped down) version of my code:
/* 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();
}
I've found out that ShiroFilter
didn't get triggered on requests. I changed my request handler to extend javax.servlet.http.HttpServlet
, now it's working!