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

Quarkus权限角色映射:注解混用报错,如何用注解实现指南效果?

Quarkus权限与角色映射问题解答

问题描述

根据Quarkus官方指南,可通过配置文件将权限映射至角色,示例代码与配置如下:

注解示例代码

@PermissionsAllowed(value = {"create", "update"}, inclusive=true) 
@POST
@Path("/modify/inclusive")
public String createOrUpdate(Long id) {
    return id + " modified";
}

@PermissionsAllowed({"see:detail", "see:all", "read"}) 
@GET
@Path("/id/{id}")
public String getItem(String id) {
    return "item-detail-" + id;
}

配置文件示例

quarkus.http.auth.policy.role-policy1.permissions.user=see:all                                       
quarkus.http.auth.policy.role-policy1.permissions.admin=create,update,read                           
quarkus.http.auth.permission.roles1.paths=/crud/modify/*,/crud/id/*                                  
quarkus.http.auth.permission.roles1.policy=role-policy1

配置说明

为拥有user角色的SecurityIdentity添加权限see:all,默认使用io.quarkus.security.StringPermission,和@PermissionsAllowed注解逻辑一致。
权限create、update、read被映射到admin角色。

但同时使用@PermissionsAllowed和@RolesAllowed注解时触发程序错误,相关代码及报错信息如下:

出错代码

public class ReadyResource {
  @Inject private ApplicationConfig applicationConfig;

  @GET()
  @Path("ready2")
  @PermissionsAllowed("read")
  @RolesAllowed("User")
  @Produces(MediaType.APPLICATION_JSON)
  public Result<ApplicationConfig> getReady2() {
    return Result.ofSuccess(applicationConfig);
  }
}

错误信息

2023-05-14 13:19:05,464 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
    [error]: Build step io.quarkus.security.deployment.SecurityProcessor#gatherSecurityChecks threw an exception: java.lang.IllegalStateException: Method hello of class org.acme.GreetingResource2 is annotated with multiple security annotations
    at io.quarkus.security.deployment.PermissionSecurityChecks$PermissionSecurityChecksBuilder.gatherPermissionsAllowedAnnotations(PermissionSecurityChecks.java:216)
    at io.quarkus.security.deployment.SecurityProcessor.gatherSecurityAnnotations(SecurityProcessor.java:673)
    at io.quarkus.security.deployment.SecurityProcessor.gatherSecurityChecks(SecurityProcessor.java:527)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
    at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
    at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
    at java.base/java.lang.Thread.run(Thread.java:1623)
    at org.jboss.threads.JBossThread.run(JBossThread.java:501)

疑问:

  • 为何配置文件方式运行正常,但混用两种注解会报错?
  • 如何仅通过注解实现指南中的权限与角色映射效果?

解答

1. 混用注解报错原因

Quarkus的安全部署处理器不允许在同一个方法上同时使用@PermissionsAllowed和@RolesAllowed这类安全注解,因为二者对应不同的安全校验逻辑:

  • @RolesAllowed是基于角色的直接校验,仅判断当前用户是否拥有指定角色
  • @PermissionsAllowed是基于权限的校验,判断当前用户是否拥有指定权限

配置文件方式是将角色和权限做映射,本质是让对应角色的用户自动具备指定权限,最终统一通过权限逻辑校验,不存在冲突;但直接混用两种注解会让处理器无法确定采用哪种校验逻辑,因此抛出multiple security annotations错误。

2. 仅用注解实现权限-角色映射的方案

要实现配置文件的角色-权限映射效果,无需混用注解,只需使用@PermissionsAllowed,再通过自定义角色权限映射器关联角色与权限:

步骤1:实现PermissionMapper接口

创建自定义权限映射器,将用户角色转换为对应权限:

import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.runtime.PermissionMapper;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

@ApplicationScoped
public class RoleToPermissionMapper implements PermissionMapper {

    @Override
    public Set<String> mapPermissions(SecurityIdentity identity) {
        // 根据用户角色映射对应权限
        return identity.getRoles().stream()
                .flatMap(role -> switch (role) {
                    case "user" -> Set.of("see:all").stream();
                    case "admin" -> Set.of("create", "update", "read").stream();
                    default -> Collections.emptySet().stream();
                })
                .collect(Collectors.toSet());
    }
}

步骤2:仅使用@PermissionsAllowed注解

在接口方法上只保留@PermissionsAllowed,无需添加@RolesAllowed:

public class ReadyResource {
  @Inject private ApplicationConfig applicationConfig;

  @GET()
  @Path("ready2")
  @PermissionsAllowed("read") // 仅指定权限,映射由自定义mapper处理
  @Produces(MediaType.APPLICATION_JSON)
  public Result<ApplicationConfig> getReady2() {
    return Result.ofSuccess(applicationConfig);
  }
}

这样,当拥有admin角色的用户访问该接口时,自定义映射器会自动为其添加read权限,从而通过@PermissionsAllowed的校验,实现和配置文件相同的效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:54:57