You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:35:59