Web 端点授权
摘要
提供有关红帽构建的 Quarkus 文档的反馈 复制链接链接已复制到粘贴板!
要报告错误或改进文档,请登录到 Red Hat JIRA 帐户并提交问题。如果您没有 Red Hat Jira 帐户,则会提示您创建一个帐户。
流程
- 单击以下链接 以创建 ticket。
- 在 Summary 中输入问题的简短描述。
- 在 Description 中提供问题或功能增强的详细描述。包括一个指向文档中问题的 URL。
- 点 Submit 创建问题,并将问题路由到适当的文档团队。
使开源包含更多 复制链接链接已复制到粘贴板!
红帽致力于替换我们的代码、文档和 Web 属性中有问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看 CTO Chris Wright 的信息。
第 1 章 Web 端点授权 复制链接链接已复制到粘贴板!
Quarkus 融合了一个可插拔的 Web 安全层。当安全性处于活动状态时,系统会对所有 HTTP 请求执行权限检查,以确定它们是否应该继续。
如果路径受 quarkus.http.auth. 配置限制,则使用 @PermitAll 将不会打开路径。为确保可以访问特定的路径,必须在 Quarkus 安全设置中进行适当的配置。
如果使用 Jakarta RESTful Web 服务,请考虑使用 quarkus.security.jaxrs.deny-unannotated-endpoints 或 quarkus.security.jaxrs.default-roles-allowed 来设置默认安全要求,而不是 HTTP 路径级别匹配,因为注解可以在单个端点上覆盖这些属性。
授权基于安全提供程序提供的用户角色。要自定义这些角色,可以创建一个 SecurityIdentityAugmentor,请参阅 安全身份自定义。
1.1. 使用配置授权 复制链接链接已复制到粘贴板!
权限通过权限集在 Quarkus 配置中定义,每个都指定了访问控制的策略。
| 内置策略 | 描述 |
|---|---|
|
| 此策略拒绝所有用户。 |
|
| 此策略允许所有用户。 |
|
| 此策略仅允许经过身份验证的用户。 |
您可以定义基于角色的策略,以允许具有特定角色的用户访问资源。
基于角色的策略示例
quarkus.http.auth.policy.role-policy1.roles-allowed=user,admin
quarkus.http.auth.policy.role-policy1.roles-allowed=user,admin
- 1
- 这将定义一个基于角色的策略,允许用户使用
用户和admin角色。
您可以通过配置 application.properties 文件中定义的内置权限集来引用自定义策略,如以下配置示例所示:
策略配置示例
示例中的确切路径 /forbidden 将不会保护 /forbidden/ 路径。为 /forbidden/ 路径添加新的准确路径,以确保适当的安全覆盖。
1.1.1. 自定义 HttpSecurityPolicy 复制链接链接已复制到粘贴板!
有时,注册您自己的命名策略可能很有用。您可以通过创建实现 io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy 接口的应用程序范围 CDI bean 来实现它,如下例所示:
- 1
- 命名 HTTP 安全策略将仅应用于与
application.properties路径匹配规则匹配的请求。
从配置文件引用的名为 HttpSecurityPolicy 的自定义示例
quarkus.http.auth.permission.custom1.paths=/custom/* quarkus.http.auth.permission.custom1.policy=custom
quarkus.http.auth.permission.custom1.paths=/custom/*
quarkus.http.auth.permission.custom1.policy=custom
- 1
- 自定义策略名称必须与
io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.name方法返回的值匹配。
您还可以在每个请求上创建全局 HttpSecurityPolicy 调用。只需实施 io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.name 方法,并将策略名称留空。
1.1.2. 匹配路径和方法 复制链接链接已复制到粘贴板!
权限集也可以将路径和方法指定为用逗号分开的列表。如果路径以 * 通配符结尾,则查询会生成与所有子路径匹配。否则,它会查询完全匹配,且只与该特定路径匹配:
quarkus.http.auth.permission.permit1.paths=/public*,/css/*,/js/*,/robots.txt quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET,HEAD
quarkus.http.auth.permission.permit1.paths=/public*,/css/*,/js/*,/robots.txt
quarkus.http.auth.permission.permit1.policy=permit
quarkus.http.auth.permission.permit1.methods=GET,HEAD
- 1
- 路径末尾的
*通配符匹配零个或多个路径片段,但从/public路径开始的任何词语。因此,/public-info等路径与此模式不匹配。
1.1.3. 匹配路径而不是方法 复制链接链接已复制到粘贴板!
如果请求根据路径匹配一个或多个权限集,但不需要的方法,则请求将被拒绝。
根据前面的权限集,GET /public/foo 将匹配路径和方法,因此被允许。相反,POST /public/foo 将匹配路径,而不是方法,因此被拒绝。
1.1.4. 匹配多个路径:路径的最成功 复制链接链接已复制到粘贴板!
匹配始终以"最长路径优先"为基础完成。如果一个更具体的权限集匹配,则不会被考虑:
根据前面的权限集,GET /public/forbidden-folder/foo 将同时匹配这两个权限集的路径。但是,由于较长的路径与 deny1 权限集的路径匹配,因此选择了 deny1,请求将被拒绝。
subPath 权限之前带有 root 路径权限,因为 deny1 和 permit1 权限示例之前演示了。
此规则通过一个场景进一步说明,其中 subpath 权限允许访问公共资源,而 root 路径权限需要授权。
1.1.5. 匹配多个子路径:到 * 通配符最长的路径 wins 复制链接链接已复制到粘贴板!
在以前的版本中,当一个路径使用 * 通配符结束时,会演示与所有子路径匹配的示例。
此通配符也适用于代表单一路径段的路径中。它不能与其他路径段字符混合;因此,路径分隔符始终将 * 通配符括起,如 /public/*/about-us 路径中所示。
当多个路径模式与同一请求路径对应时,系统会选择最长的子路径,从而导致 * 通配符。在这种情况下,每个路径片段字符都比 * 通配符更具体。
以下是一个简单的示例:
quarkus.http.auth.permission.secured.paths=/api/*/detail quarkus.http.auth.permission.secured.policy=authenticated quarkus.http.auth.permission.public.paths=/api/public-product/detail quarkus.http.auth.permission.public.policy=permit
quarkus.http.auth.permission.secured.paths=/api/*/detail
quarkus.http.auth.permission.secured.policy=authenticated
quarkus.http.auth.permission.public.paths=/api/public-product/detail
quarkus.http.auth.permission.public.policy=permit
应该测试使用配置通过授权保护的所有路径。使用多个通配符编写路径模式可能很繁琐。请确保路径已如预期授权。
在以下示例中,路径从最特定于最具体的路径排序:
请求路径 /one/two/three/four/five 匹配从最特定于最具体的路径排序
路径末尾的 * 通配符与零个或多个路径片段匹配。* 通配符放置在其它任何位置与一个路径片段匹配。
1.1.6. 匹配多个路径:最具体的方法胜出 复制链接链接已复制到粘贴板!
当使用多个权限集注册路径时,权限集会明确指定与请求匹配的 HTTP 方法。在本实例中,只有请求方法与方法规格不匹配时,没有方法的权限集才会生效。
前面的权限集显示 GET /public/foo 与这两个权限集的路径匹配。如何,它特别符合 permit1 权限集的显式方法。选择 permit1,并接受请求。
相反,PUT /public/foo 与 allow 1 的方法不匹配。因此,会激活 deny1,从而导致请求拒绝。
1.1.7. 匹配多个路径和方法:它们都成功 复制链接链接已复制到粘贴板!
有时,前面描述的规则允许同时有多个权限集 win。在这种情况下,要进行请求,所有权限都必须允许访问。要实现此目的,两者都必须指定方法或没有方法。特定于方法的匹配优先。
根据前面的权限集,GET /api/foo 将匹配权限集的路径,这需要 用户和 admin 角色。
1.1.8. 拒绝访问的配置属性 复制链接链接已复制到粘贴板!
以下配置设置更改基于角色的访问控制(RBAC)拒绝行为:
quarkus.security.jaxrs.deny-unannotated-endpoints=true|false-
如果设置为 true,则默认拒绝所有 Jakarta REST 端点的访问。如果 Jakarta REST 端点没有安全注解,则默认为
@DenyAll行为。这有助于避免意外公开应该被保护的端点。默认值为false。 quarkus.security.jaxrs.default-roles-allowed=role1,role2-
定义未注解端点的默认角色要求。
**角色是一个特殊的角色,代表任何经过身份验证的用户。这不能与deny-unannotated-endpoints结合使用,因为deny会生效。 quarkus.security.deny-unannotated-members=true|false-
如果设置为 true,则拒绝访问所有 CDI 方法和没有安全注解的 Jakarta REST 端点,但在包含安全注解方法的类中定义。默认值为
false。
1.1.9. 禁用权限 复制链接链接已复制到粘贴板!
构建时可以禁用权限,每个声明的权限 都启用了 属性,例如:
quarkus.http.auth.permission.permit1.enabled=false quarkus.http.auth.permission.permit1.paths=/public/*,/css/*,/js/*,/robots.txt quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET,HEAD
quarkus.http.auth.permission.permit1.enabled=false
quarkus.http.auth.permission.permit1.paths=/public/*,/css/*,/js/*,/robots.txt
quarkus.http.auth.permission.permit1.policy=permit
quarkus.http.auth.permission.permit1.methods=GET,HEAD
使用系统属性或环境变量在运行时可以重新启用权限,例如: -Dquarkus.http.auth.permission.permit1.enabled=true。
1.1.10. 权限路径和 HTTP 根路径 复制链接链接已复制到粘贴板!
quarkus.http.root-path 配置属性更改 http 端点上下文路径。
默认情况下,quarkus.http.root-path 会自动添加到配置的权限路径前,然后不要使用正斜杠,例如:
quarkus.http.auth.permission.permit1.paths=public/*,css/*,js/*,robots.txt
quarkus.http.auth.permission.permit1.paths=public/*,css/*,js/*,robots.txt
此配置等同于以下内容:
quarkus.http.auth.permission.permit1.paths=${quarkus.http.root-path}/public/*,${quarkus.http.root-path}/css/*,${quarkus.http.root-path}/js/*,${quarkus.http.root-path}/robots.txt
quarkus.http.auth.permission.permit1.paths=${quarkus.http.root-path}/public/*,${quarkus.http.root-path}/css/*,${quarkus.http.root-path}/js/*,${quarkus.http.root-path}/robots.txt
前面斜杠会改变配置的权限路径的解释方式。配置的 URL 用于按原样使用,如果 quarkus.http.root-path 的值发生了变化,则不会调整路径。
Example:
quarkus.http.auth.permission.permit1.paths=/public/*,css/*,js/*,robots.txt
quarkus.http.auth.permission.permit1.paths=/public/*,css/*,js/*,robots.txt
此配置仅影响从固定或静态 URL 提供的资源 /public,如果 quarkus.http.root-path 已设置为 / 以外的其他路径,则这可能与您的应用程序资源不匹配。
如需更多信息,请参阅 Quarkus 中的路径解析。
1.1.11. 映射 SecurityIdentity 角色 复制链接链接已复制到粘贴板!
获奖基于角色的策略可以将 SecurityIdentity 角色映射到特定于部署的角色。然后,这些角色适用于使用 @RolesAllowed 注释的端点授权。
quarkus.http.auth.policy.admin-policy1.roles.admin=Admin1 quarkus.http.auth.permission.roles1.paths=/* quarkus.http.auth.permission.roles1.policy=admin-policy1
quarkus.http.auth.policy.admin-policy1.roles.admin=Admin1
quarkus.http.auth.permission.roles1.paths=/*
quarkus.http.auth.permission.roles1.policy=admin-policy1
- 1
- 将
admin角色映射到Admin1角色。SecurityIdentity将同时具有admin和Admin1角色。
1.2. 使用注解的授权 复制链接链接已复制到粘贴板!
红帽构建的 Quarkus 包含内置的安全性,允许基于通用安全注解 @RolesAllowed、@DenyAll、@PermitAll on REST 端点和 CDI Bean 进行 基于角色的访问控制(RBAC)。
| 注解类型 | 描述 |
|---|---|
|
| 指定不允许安全角色调用指定方法。 |
|
| 指定允许所有安全角色调用指定方法。
|
|
| 指定允许访问应用中的方法的安全角色列表。
作为等同于 |
以下 SubjectExposingResource 示例演示了 一个端点,它使用 Jakarta REST 和 Common Security 注解来描述和保护其端点。
SubjectExposingResource 示例
- 1
/subject/secured端点需要一个经过身份验证的用户,并通过使用@RolesAllowed ("Tester")注解来赋予"Tester"角色。- 2
- 端点从 Jakarta REST
SecurityContext获取用户主体。这会为安全端点返回非null。 - 3
/subject/unsecured端点通过指定@PermitAll注释来允许未经身份验证的访问。- 4
- 如果调用者通过身份验证,则获取用户主体的调用会返回
null,如果调用者是未经身份验证的且非null。 - 5
/subject/denied端点声明@DenyAll注释,不允许所有直接访问它作为 REST 方法,无论用户调用它。这个方法仍然可以通过此类中的其他方法在内部调用。
如果您计划在 IO 线程上使用标准安全注解,请查看 主动身份验证 中的信息。
@RolesAllowed 注释值支持属性 表达式,包括默认值和嵌套属性表达式。与注解搭配使用的配置属性在运行时解析。
| 注解 | 值解释 |
|---|---|
|
|
端点允许用户具有由 |
|
| 显示值可以包含多个变量的示例。 |
|
|
默认值演示。所需的角色由 |
@RolesAllowed 注释中的属性表达式用法示例
主题访问控制示例
- 1
@RolesAllowed注释值设为Administrator的值。- 2
- 这个
/subject/software-tester端点需要一个经过身份验证的用户,它被授予了 "Software-Tester" 角色。可以在角色定义中使用多个表达式。 - 3
- 此
/subject/user端点需要一个经过身份验证的用户,它已通过使用@RolesAllowed ("${customer:User}")注解授予角色"User",因为我们没有设置配置属性客户。 - 4
- 在生产环境中,这个
/subject/secured端点需要一个具有User角色的经过身份验证的用户。在开发模式中,它允许任何经过身份验证的用户。 - 5
- 属性表达式
all-roles将被视为集合类型列表,因此角色管理员、软件、测试程序和用户可以访问端点。
1.2.1. 权限注解 复制链接链接已复制到粘贴板!
Quarkus 还提供 io.quarkus.security.PermissionsAllowed 注解,它授权具有给定权限访问资源的任何经过身份验证的用户。此注解是通用安全注解的扩展,并检查授予 SecurityIdentity 实例的权限。
使用 @PermissionsAllowed 注释保护的端点示例
- 1
- 资源方法
createOrUpdate只能供具有create和update权限的用户访问。 - 2
- 默认情况下,至少需要一个注解实例指定的权限之一。您可以通过设置
inclusive=true来要求所有权限。这两种资源方法都createOrUpdate具有相同的授权要求。 - 3
- 如果
SecurityIdentity具有读取权限或查看权限以及all或detail操作之一,则访问权限会被授予getItem。 - 4
- 您可以使用您首选的
java.security.Permission实现。默认情况下,基于字符串的权限由io.quarkus.security.StringPermission执行。 - 5
- 权限不是 Bean,因此使用
Arc.container ()以编程方式获取 bean 实例。
如果您计划在 IO 线程上使用 @PermissionsAllowed,请查看 主动身份验证 中的信息。
由于 Quarkus 拦截器的限制,在类级别上不可重复 @PermissionsAllowed。如需更多信息,请参阅 Quarkus "CDI 参考" 指南中的 Repeatable interceptor bindings 部分。
将权限添加到启用了角色的 SecurityIdentity 实例的最简单方法是将角色映射到权限。使用带有配置的 Authorization 将 CRUDResource 端点所需的 SecurityIdentity 权限授予经过身份验证的用户,如下例所示:
- 1
- 将权限
see和操作添加到用户角色的SecurityIdentity实例。同样,对于@PermissionsAllowed注释,默认为使用io.quarkus.security.StringPermission。 - 2
- 权限
创建、update和read映射到角色admin。 - 3
- 4
- 您可以指定
java.security.Permission类的自定义实现。自定义类必须精确定义一个构造器,接受权限名称和可选的操作,如String数组。在这种情况下,权限列表被添加到SecurityIdentity实例中,作为新的 CustomPermission ("。list")
您还可以使用额外的构造器参数创建自定义 java.security.Permission 类。这些额外参数与通过 @PermissionsAllowed 注释注释的方法的参数匹配。之后,Quarkus 使用实际参数实例化您的自定义权限,其方法被调用 @PermissionsAllowed。
接受额外参数的自定义 java.security.Permission 类示例
- 1
- 自定义
权限类必须正好有一个构造器。第一个参数始终被视为权限名称,且必须是String类型。Quarkus 可以选择性地将权限操作传给构造器。要发生这种情况,请将第二个参数声明为String[]。
如果允许 SecurityIdentity 执行必要的操作之一,则 LibraryPermission 类允许访问当前或父库,如 读取、写入或 列表。
以下示例演示了如何使用 LibraryPermission 类:
使用 LibraryPermission保护的资源示例
与 CRUDResource 示例类似,以下示例演示了如何授予用户具有 admin 角色权限的用户来更新 MediaLibrary :
quarkus.http.auth.policy.role-policy3.permissions.admin=media-library:list,media-library:read,media-library:write quarkus.http.auth.policy.role-policy3.permission-class=org.acme.library.MediaLibraryPermission quarkus.http.auth.permission.roles3.paths=/library/* quarkus.http.auth.permission.roles3.policy=role-policy3
quarkus.http.auth.policy.role-policy3.permissions.admin=media-library:list,media-library:read,media-library:write
quarkus.http.auth.policy.role-policy3.permission-class=org.acme.library.MediaLibraryPermission
quarkus.http.auth.permission.roles3.paths=/library/*
quarkus.http.auth.permission.roles3.policy=role-policy3
- 1
- 授予权限
media-library,允许读取、写和list操作。由于MediaLibrary是TvLibrary类父项,因此也允许具有admin角色的用户修改TvLibrary。
/libraryAttr 路径可以从 Keycloak 供应商 Dev UI 页面中测试,因为用户 alice 由 Keycloak 的 Dev Services 自动创建的用户具有 admin 角色。
目前为止提供的示例演示角色到权限映射。也可以以编程方式向 SecurityIdentity 实例添加权限。在以下示例中,SecurityIdentity 被自定义,以添加之前通过基于 HTTP 基于角色的访问控制相同的权限。
以编程方式将 LibraryPermission 添加到 SecurityIdentity的示例
基于注解的权限无法用于自定义 Jakarta REST SecurityContexts,因为 jakarta.ws.rs.core.SecurityContext 中没有权限。