我正在尝试为嵌入式 Jetty 12 服务器添加安全性。
什么有效:
什么不起作用:
这是我的代码:
public WebsocketServer(int port, Model model, SessionManager sessionManager) throws Exception {
server_ = new Server(port);
server_.setRequestLog(new CustomRequestLog(new Slf4jRequestLogWriter(), CustomRequestLog.EXTENDED_NCSA_FORMAT));
SessionHandler sessionHandler = new SessionHandler();
server_.setHandler(sessionHandler);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
sessionHandler.setHandler(security);
HashLoginService loginService = new HashLoginService("login");
try (ResourceFactory.Closeable rf = ResourceFactory.closeable()) {
Path pw = Paths.get("cfg/web.passwords");
log_.info("Configuring login passwords from {} {}", pw, pw.toFile().exists());
Resource r = rf.newResource(pw);
loginService.setConfig(r);
security.setLoginService(loginService);
}
FormAuthenticator formAuthenticator = new FormAuthenticator("/login", "/login", true);
//formAuthenticator.setAlwaysSaveUri(true);
security.setAuthenticator(formAuthenticator);
ConstraintMapping cm = new ConstraintMapping();
cm.setPathSpec("/model/*");
cm.setConstraint(Constraint.from("admin"));
security.setConstraintMappings(Collections.singletonList(cm));
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
security.setHandler(contextHandlerCollection);
// add a context for /model
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
servletContextHandler.setContextPath("/model");
servletContextHandler.addServlet(new ServletHolder(new ModelServlet(model)), "/*");
contextHandlerCollection.addHandler(servletContextHandler);
// add a context for /web
servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
servletContextHandler.setContextPath("/web");
servletContextHandler.setWelcomeFiles(new String[]{"websocket.html"});
Resource webResource = ResourceFactory.of(servletContextHandler).newResource(Paths.get("cfg/web"));
if (!Resources.isReadableDirectory(webResource))
throw new FileNotFoundException("Unable to find web resource");
ServletHolder holderWeb = new ServletHolder("web", DefaultServlet.class);
holderWeb.setInitParameter("baseResource", webResource.getURI().toASCIIString());
holderWeb.setInitParameter("dirAllowed", "false");
holderWeb.setInitParameter("pathInfoOnly", "true");
servletContextHandler.addServlet(holderWeb, "/*");
// allow websocket upgrades in this context
JettyWebSocketServletContainerInitializer.configure(servletContextHandler, (context, configurator) ->
{
configurator.setIdleTimeout(Duration.ofMillis(30000));
configurator.addMapping("/ws", (req, res) -> {
Session s = new Session(req);
sessionManager.add(s);
return s;
});
});
contextHandlerCollection.addHandler(servletContextHandler);
// add a context for the login page
servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
servletContextHandler.setContextPath("/login");
servletContextHandler.addServlet(new ServletHolder(new FormAuthServlet()), "/*");
contextHandlerCollection.addHandler(servletContextHandler);
// add a context for the root
servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
Resource baseResource = ResourceFactory.of(servletContextHandler).newResource(Paths.get("cfg/web"));
if (!Resources.isReadableDirectory(baseResource))
throw new FileNotFoundException("Unable to find base resource");
servletContextHandler.setBaseResource(baseResource);
ServletHolder servletHolder = new ServletHolder("root", DefaultServlet.class);
servletContextHandler.addServlet(servletHolder, "/*");
contextHandlerCollection.addHandler(servletContextHandler);
server_.start();
//server.join();
}
(顺便说一句,我不知道我是否正确链接了 Session、Security 和 ContextHandler)
事实证明,我的登录表单的操作是“j_security_check”而不是“/j_security_check”。当我使用正确的操作时,一切都会正常工作。