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

Jersey中RolesAllowedDynamicFeature未触发的配置问题咨询

Jakarta EE无web.xml项目中RolesAllowedDynamicFeature授权逻辑不生效问题

项目相关代码

Jakarta Application类

@ApplicationPath("/app")
@RolesAllowed("admin")
public class Application extends ResourceConfig {
    public Application() {
        System.out.println("!!!!!! Insights starts !!!!!....");
        packages("com.company.application.ws");
        register(RolesAllowedDynamicFeature.class);
        register(SecurityFilter.class);
        register(AuthenticationExceptionMapper.class);
    }
}

自定义授权过滤器SecurityFilter

@Provider
@PreMatching
public class SecurityFilter implements ContainerRequestFilter {

    @Inject
    jakarta.inject.Provider<UriInfo> uriInfo;
//    @Inject
//    private UserService userService;
    private static final String REALM = "My App";

    @Override
    public void filter(ContainerRequestContext filterContext) throws IOException {
        User user = authenticate(filterContext);
        filterContext.setSecurityContext(new Authorizer(user));
    }

    private User authenticate(ContainerRequestContext filterContext) {
        // 提取认证凭证
        String authentication = filterContext.getHeaderString(HttpHeaders.AUTHORIZATION);
        if (authentication == null) {
            throw new AuthenticationException("Authentication credentials are required", REALM);
        }
        if (!authentication.startsWith("Basic ")) {
            return null;
            // 此处应添加额外校验逻辑
            // "仅支持HTTP Basic认证"
        }
        authentication = authentication.substring("Basic ".length());
        String[] values = new String(DatatypeConverter.parseBase64Binary(authentication), StandardCharsets.US_ASCII).split(":");
        if (values.length < 2) {
            throw new WebApplicationException(400);
            // "用户名密码格式无效"
        }
        String username = values[0];
        String password = values[1];
        if ((username == null) || (password == null)) {
            throw new WebApplicationException(400);
            // "缺少用户名或密码"
        }

        // 校验提取的凭证
        User user;
        if (username.equals("admin") && password.equals("1234")) {
            user = new User("admin", "admin");
            System.out.println("admin AUTHENTICATED");
        } else if (username.equals("user") && password.equals("123")) {
            user = new User("user", "user");
            System.out.println("user AUTHENTICATED");
        } else {
            System.out.println("USER NOT AUTHENTICATED");
            throw new AuthenticationException("Invalid username or password", REALM);
        }
        return user;
    }

    public class Authorizer implements SecurityContext {

        private final User user;
        private final Principal principal;

        public Authorizer(final User user) {
            this.user = user;
            this.principal = () -> user.username;
        }

        @Override
        public Principal getUserPrincipal() {
            return this.principal;
        }

        @Override
        public boolean isUserInRole(String role) {
            return (role.equals(user.role));
        }

        @Override
        public boolean isSecure() {
            return "https".equals(uriInfo.get().getRequestUri().getScheme());
        }

        @Override
        public String getAuthenticationScheme() {
            return SecurityContext.BASIC_AUTH;
        }
    }

    public static class User {

        public String username;
        public String role;

        public User(String username, String role) {
            this.username = username;
            this.role = role;
        }
    }
}

问题描述

RolesAllowedDynamicFeature从未被触发,已在Application类、资源类及方法级别添加@RolesAllowed注解,但均无效,isUserInRole方法从未被调用。

更新情况

复制本地版本的RolesAllowedDynamicFeature并注册后,RolesAllowedDynamicFeature.configure和RolesAllowedRequestFilter(String[] rolesAllowed)构造函数已触发,但RolesAllowedRequestFilter.filter和RolesAllowedRequestFilter.isAuthenticated仍未被调用。


解决方案建议

  • 移除@PreMatching注解:SecurityFilter使用的@PreMatching会让过滤器在请求匹配资源之前执行,而RolesAllowedRequestFilter是在资源匹配后才触发的,这会导致认证完成后授权逻辑无法正常触发。去掉该注解,让SecurityFilter在默认请求阶段执行。

  • 指定过滤器执行优先级:给SecurityFilter添加@Priority(Priorities.AUTHENTICATION)注解,确保认证逻辑先于授权执行(RolesAllowedRequestFilter默认使用Priorities.AUTHORIZATION优先级)。

  • 校验资源类注解配置:确认资源类/方法上的@RolesAllowed注解无冲突(比如没有@PermitAll注解覆盖),同时检查packages("com.company.application.ws")是否正确包含了目标资源类。

  • 检查SecurityContext设置:确保SecurityFilter中设置SecurityContext的操作未被后续过滤器覆盖,且设置时机正确。


内容的提问来源于stack exchange,提问作者khateeb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:03:09