如何为Jetty 12的PathMappingsHandler添加安全处理器?
Jetty 12 为指定路径添加认证拦截的实现方案
针对你用Handler.Abstract搭建的Jetty 12服务,要给/users路径添加认证拦截,可通过Jetty内置的SecurityHandler组件实现,以下是具体步骤和代码示例:
1. 配置登录服务(用户与角色管理)
先创建登录服务,用于存储用户凭证和角色信息,这里用Jetty提供的内存实现HashLoginService(生产环境建议替换为数据库驱动的JDBCLoginService):
// 创建领域名称为"MyRealm"的登录服务 HashLoginService loginService = new HashLoginService("MyRealm"); // 添加用户:用户名、密码、角色数组 loginService.putUser("admin", new Password("admin123"), new String[]{"USER"}); loginService.putUser("testuser", new Password("test123"), new String[]{"USER"}); // 将登录服务注册到Jetty Server server.addBean(loginService);
2. 创建SecurityHandler包装目标Handler
用SecurityHandler包装UsersHandler,并配置认证规则:
// 初始化安全处理器 SecurityHandler securityHandler = new SecurityHandler(); // 配置约束映射:指定路径、认证方式、所需角色 ConstraintMapping constraintMapping = new ConstraintMapping(); // 匹配/users路径及其子路径 constraintMapping.setPathSpec("/users/*"); Constraint constraint = new Constraint(); // 使用Basic认证(适合API场景,若需网页表单认证见后续说明) constraint.setName(Constraint.__BASIC_AUTH); // 设置允许访问的角色,只有拥有USER角色的用户可访问 constraint.setRoles(new String[]{"USER"}); // 开启强制认证 constraint.setAuthenticate(true); constraintMapping.setConstraint(constraint); // 绑定约束映射到安全处理器 securityHandler.setConstraintMappings(new ConstraintMapping[]{constraintMapping}); // 关联登录服务 securityHandler.setLoginService(loginService); // 将UsersHandler设置为安全处理器的下游处理器(认证通过后才会调用) securityHandler.setHandler(new UsersHandler());
3. 修改路径映射配置
将原PathMappingsHandler中/users对应的UsersHandler替换为包装后的SecurityHandler:
PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); pathMappingsHandler.addMapping(PathSpec.from("/"), new IndexHandler()); // 替换为带认证的securityHandler pathMappingsHandler.addMapping(PathSpec.from("/users"), securityHandler); Handler.Sequence handlers = new Handler.Sequence(); handlers.addHandler(pathMappingsHandler); handlers.addHandler(new DefaultHandler()); server.setHandler(handlers);
可选:切换为表单认证(网页场景)
如果是Web页面场景,更适合用表单认证,只需修改SecurityHandler的认证器,并添加登录页面的Handler:
配置表单认证器
// 替换Basic认证器为表单认证器 // 参数说明:登录页面路径、登录失败跳转路径、是否启用SSL securityHandler.setAuthenticator(new FormAuthenticator("/login", "/login?error", false));
添加登录页面Handler
public class LoginPageHandler extends Handler.Abstract { @Override public boolean handle(Request request, Response response, Callback callback) throws Exception { // 获取登录失败的错误标记 String errorFlag = request.getParameter("error"); StringBuilder htmlContent = new StringBuilder(); htmlContent.append("<html><head><title>用户登录</title></head><body>"); if (errorFlag != null) { htmlContent.append("<p style='color:red'>用户名或密码错误,请重试</p>"); } // Jetty表单认证默认提交路径为/j_security_check,参数名固定为j_username和j_password htmlContent.append("<form method='POST' action='/j_security_check'>") .append("用户名:<input type='text' name='j_username' required><br>") .append("密码:<input type='password' name='j_password' required><br>") .append("<button type='submit'>登录</button>") .append("</form></body></html>"); response.setStatus(HttpStatus.OK_200); response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/html; charset=UTF-8"); Content.Sink.write(response, true, htmlContent.toString(), callback); return true; } }
注册登录页面路径
// 在PathMappingsHandler中添加登录页面映射 pathMappingsHandler.addMapping(PathSpec.from("/login"), new LoginPageHandler());
关键注意事项
HashLoginService仅用于测试,生产环境必须使用持久化的登录服务(如JDBCLoginService)- 认证方式选择:Basic认证适合API接口,表单认证适合Web前端页面
- 角色权限可按需扩展,比如添加ADMIN角色并配置对应路径的约束
- 确保
SecurityHandler的路径规则与PathMappingsHandler的映射匹配,避免拦截范围错误
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

