php小编百草为您精心撰写了一篇关于使用aad和aws cognito保护spring boot rest api的java问答文章。在这篇文章中,我们将探讨如何利用这两种身份验证服务来保护不同端点,确保您的api安全可靠。跟随我们的指引,学习如何在您的spring boot项目中实现身份验证和授权,让您的rest api更加强大和可靠。
希望有人可以在这里帮助我,因为我在任何地方都找不到有关此主题的任何资源。
我有一个 spring boot restapi,当前配置有两种路由:1. 未经授权 2. 通过 aad/entra 的 bearer 授权
我的配置方法当前设置如下:
@override
protected void configure(httpsecurity http) throws exception {
super.configure(http);
http.csrf().disable();
http.authorizerequests(requests -> requests
.antmatchers(httpmethod.options, "/**/**").permitall()
.antmatchers("/api/protected/**").fullyauthenticated()
.anyrequest().permitall()
);
}
它包装在一个扩展 aadresourceserverwebsecurityconfigureradapter 的类中。
通过以这种方式配置我们的 api,我们能够按如下方式保护我们的路由:
@preauthorize("hasauthority('approle_appname.rolename')")
@getmapping(value = "/some-method", produces = mediatype.application_json_value)
public responseentity<list<string>> getstrings() {
return responseentity.ok(...);
}
我们的 api 现在应该进行扩展,以允许新型用户使用授权端点。这些用户由 aws cognito 管理。如何设置我的 websecurityconfigureradapter 以允许某些路径未经授权,某些路径通过 aad 进行保护,某些路径通过 aws cognito 进行保护?
我似乎遇到的主要问题是 aadresourceserverwebsecurityconfigureradapter 以这样的方式配置 jwt 验证,它仅适用于 microsoft 提供的 bearers。
理想情况下我想要这样的东西:
@configuration
@enablewebsecurity
@enableglobalmethodsecurity(prepostenabled = true)
public class securityconfig extends websecurityconfigureradapter {
@configuration
@order(1)
public static class azureadsecurityconfig extends aadresourceserverwebsecurityconfigureradapter {
@override
protected void configure(httpsecurity http) throws exception {
http.authorizerequests(requests -> requests
.antmatchers("/api/aad/**").fullyauthenticated()
);
http.oauth2resourceserver().jwt([utilize aad jwt validation]);
}
}
@configuration
@order(2)
public static class awscognitosecurityconfig extends websecurityconfigureradapter {
@override
protected void configure(httpsecurity http) throws exception {
http.authorizerequests(requests -> requests
.antmatchers("/api/cognito/**").fullyauthenticated()
);
http.oauth2resourceserver().jwt([utilize aws cognito jwt validation]);
}
}
@configuration
@order(3)
public static class defaultsecurityconfig extends websecurityconfigureradapter {
@override
protected void configure(httpsecurity http) throws exception {
http.csrf().disable();
http.authorizerequests(requests -> requests
.antmatchers(httpmethod.options, "/**/**").permitall()
.anyrequest().permitall()
);
}
}
}
我发现的另一个问题是 aadresourceserverwebsecurityconfigureradapter 自动将 jwtclaimnames“roles”和“scp”的所有可能的前缀设置为“scope_”和“approle_”。理想情况下,我希望 aad 和 aws cognito 的它们有所不同,以便我将“aad_scope_”、“aad_approle_”和“cognito_group_”作为前缀。
我找到了一些资料解释如何为 spring boot 实现多租户 jwt 验证,但它们都仅使用 sql 数据库实现基于密码/用户的身份验证。
有没有办法基本上必须重新实现所有 aad 逻辑,以便我可以混合对 aws cognito 给出的 jwt 的验证,或者有没有办法根据路由进行决定?
我已经知道您可以在 httpsecurity 上使用 oauth2resourceserver() 函数来配置 jwt 使用情况,但我只找到有关如何为单个租户实现该功能的信息。
如果有人已经成功实施了这个特定或类似的案例,或者可以将我推向正确的方向,我将非常感激。 或者也许我的想法是完全错误的,那么请告诉我。
感谢 @ch4mp 的回答,我已经成功了。 >工作答案<
现在我的实现已经高度简化,如下所示:
应用程序.yml
com:
c4-soft:
springaddons:
oidc:
ops:
- iss: https://cognito-idp.<region>.amazonaws.com/<cognito-pool>
authorities:
- path: $.cognito:groups
prefix: cognito_group_
- iss: https://sts.windows.net/<entra objectid>/
authorities:
- path: $.roles.*
prefix: aad_approle_
- path: $.scp
prefix: aad_scope_
aud: <enterprise application id>
resource-server:
permit-all:
- /api/route/noauth
安全配置
package some.package;
import org.springframework.context.annotation.configuration;
import org.springframework.security.config.annotation.method.configuration.enablemethodsecurity;
import org.springframework.security.config.annotation.web.configuration.enablewebsecurity;
@enablewebsecurity
@enablemethodsecurity
@configuration
public class securityconfig { }
我的控制器现在看起来像这样:
package some.package;
import org.springframework.http.responseentity;
import org.springframework.security.access.prepost.preauthorize;
import org.springframework.security.core.context.securitycontextholder;
import org.springframework.security.oauth2.jwt.jwt;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;
@restcontroller
@requestmapping("/api/route")
public class jwttestcontroller {
@getmapping("/aadauth")
@preauthorize("hasauthority('aad_approle_grantedapprole.xxx')")
public responseentity<string> aadauthrole() {
jwt jwt = (jwt) securitycontextholder.getcontext().getauthentication().getprincipal();
return responseentity.ok(jwt.getclaims().tostring());
}
@getmapping("/aadauth")
@preauthorize("hasauthority('aad_scope_grantedscope.xxx')")
public responseentity<string> aadauthscope() {
jwt jwt = (jwt) securitycontextholder.getcontext().getauthentication().getprincipal();
return responseentity.ok(jwt.getclaims().tostring());
}
@preauthorize("hasauthority('cognito_group_somegroup')")
@getmapping("/cognitoauth")
public responseentity<string> cognitoauth() {
jwt jwt = (jwt) securitycontextholder.getcontext().getauthentication().getprincipal();
return responseentity.ok(jwt.getclaims().tostring());
}
@getmapping("/noauth")
public responseentity<string> noauth() {
return responseentity.ok("hello world!");
}
}
构建.gradle
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'com.c4-soft.springaddons:spring-addons-starter-oidc:7.3.5'这不是 spring 的官方启动器,而是 oss 实现:https://www.php.cn/link/49844ba129a1cbc3d964703fcdb756ba
如果我遇到任何其他问题,我会再次更新,但目前它正在工作。
我将在这里公开一个使用 my starter 的解决方案,因为它更容易。
如果您更喜欢仅使用“官方”spring boot 启动器构建安全配置,则必须使用 iss 声明提供自己的 authenticationmanagerresolver<httpservletrequest>,每个身份验证管理器都有自己的身份验证转换器和自己的权限转换器来处理源声明和您想要的前缀。浏览 my tutorials 或 official documentation 以获取示例和实施提示。 This other answer 也可以提供帮助(权限映射要求完全不同,但身份验证管理器解析器类似)。
3.2.2 和 spring-addons<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://maven.apache.org/pom/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelversion>4.0.0</modelversion>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>3.2.2</version>
<relativepath/> <!-- lookup parent from repository -->
</parent>
<groupid>com.c4-soft.demo</groupid>
<artifactid>multi-tenant-resource-server</artifactid>
<version>0.0.1-snapshot</version>
<properties>
<java.version>21</java.version>
<spring-addons.version>7.3.5</spring-addons.version>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-oauth2-resource-server</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>com.c4-soft.springaddons</groupid>
<artifactid>spring-addons-starter-oidc</artifactid>
<version>${spring-addons.version}</version>
</dependency>
<dependency>
<groupid>com.c4-soft.springaddons</groupid>
<artifactid>spring-addons-starter-oidc-test</artifactid>
<version>${spring-addons.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-maven-plugin</artifactid>
</plugin>
</plugins>
</build>
</project>
@configuration
@enablemethodsecurity
public class securityconf {
}
编辑以下 application.yaml 以放置您自己的发行者:
com:
c4-soft:
springaddons:
oidc:
ops:
- iss: https://cognito-idp.us-west-2.amazonaws.com/us-west-2_rzhmglwjl
authorities:
- path: $.cognito:groups
prefix: cognito_group_
- iss: https://sts.windows.net/0a962d63-6b23-4416-81a6-29f88c553998/
authorities:
- path: $.approles.*.displayname
prefix: aad_approle_
- path: $.scope
prefix: aad_scope_
resourceserver:
# spring-addons whitelist is for permitall() (rather than isauthenticated())
# which is probably much safer
permit-all:
- /actuator/health/readiness
- /actuator/health/liveness
- /v3/api-docs/**
- /api/public/**
上面 path 的值是 json 路径。您可以使用 jsonpath.com 等工具根据您自己的令牌有效负载(使用 jwt.io 等工具提取)测试路径表达式。
是的,就这么简单。不,我没有省略任何 yaml 属性或 java 配置(如果您不相信我,只需在新项目中进行测试)。
@restcontroller
public class greetcontroller {
@getmapping("/greet")
@preauthorize("isauthenticated()")
public string getgreet(authentication auth) {
return "hello %s! you are granted with %s.".formatted(auth.getname(), auth.getauthorities());
}
@getmapping(value = "/strings")
@preauthorize("hasanyauthority('aad_approle_admin', 'cognito_group_admin')")
public list<string> getstrings() {
return list.of("protected", "strings");
}
}
@webmvctest(controllers = greetcontroller.class)
@autoconfigureaddonswebmvcresourceserversecurity
@import(securityconf.class)
class greetcontrollertest {
@autowired
mockmvcsupport api;
@test
@withanonymoususer
void givenuserisanonymous_whengetgreet_thenunauthorized() throws unsupportedencodingexception, exception {
api.get("/greet").andexpect(status().isunauthorized());
}
@test
@withjwt("aad_admin.json")
void givenuserisaadadmin_whengetgreet_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/greet").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals(
"hello aad-admin! you are granted with [aad_approle_msiam_access, aad_approle_admin, aad_scope_openid, aad_scope_profile, aad_scope_machin:truc].",
actual);
}
@test
@withjwt("cognito_admin.json")
void givenuseriscognitoadmin_whengetgreet_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/greet").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals("hello amazon-cognito-admin! you are granted with [cognito_group_admin, cognito_group_machin:truc].", actual);
}
@test
@withjwt("aad_machin-truc.json")
void givenuserisaadmachintruc_whengetgreet_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/greet").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals("hello aad-user! you are granted with [aad_approle_msiam_access, aad_scope_openid, aad_scope_profile, aad_scope_machin:truc].", actual);
}
@test
@withjwt("cognito_machin-truc.json")
void givenuseriscognitomachintruc_whengetgreet_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/greet").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals("hello amazon-cognito-user! you are granted with [cognito_group_machin:truc].", actual);
}
@test
@withanonymoususer
void givenuserisanonymous_whengetstrings_thenunauthorized() throws unsupportedencodingexception, exception {
api.get("/strings").andexpect(status().isunauthorized());
}
@test
@withjwt("aad_admin.json")
void givenuserisaadadmin_whengetstrings_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/strings").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals("[\"protected\",\"strings\"]", actual);
}
@test
@withjwt("cognito_admin.json")
void givenuseriscognitoadmin_whengetstrings_thenok() throws unsupportedencodingexception, exception {
final var actual = api.get("/strings").andexpect(status().isok()).andreturn().getresponse().getcontentasstring();
assertequals("[\"protected\",\"strings\"]", actual);
}
@test
@withjwt("aad_machin-truc.json")
void givenuserisaadmachintruc_whengetstrings_thenforbidden() throws unsupportedencodingexception, exception {
api.get("/strings").andexpect(status().isforbidden());
}
@test
@withjwt("cognito_machin-truc.json")
void givenuseriscognitomachintruc_whengetstrings_thenforbidden() throws unsupportedencodingexception, exception {
api.get("/strings").andexpect(status().isforbidden());
}
}
使用此测试资源:
aad_admin.json{
"sub": "aad-admin",
"iss": "https://sts.windows.net/0a962d63-6b23-4416-81a6-29f88c553998/",
"approles": [
{
"allowedmembertypes": [
"user"
],
"description": "msiam_access",
"displayname": "msiam_access",
"id": "ef7437e6-4f94-4a0a-a110-a439eb2aa8f7",
"isenabled": true,
"origin": "application",
"value": null
},
{
"allowedmembertypes": [
"user"
],
"description": "administrators only",
"displayname": "admin",
"id": "4f8f8640-f081-492d-97a0-caf24e9bc134",
"isenabled": true,
"origin": "serviceprincipal",
"value": "administrator"
}
],
"scope": "openid profile machin:truc"
}
aad_machin-truc.json{
"sub": "aad-user",
"iss": "https://sts.windows.net/0a962d63-6b23-4416-81a6-29f88c553998/",
"approles": [
{
"allowedmembertypes": [
"user"
],
"description": "msiam_access",
"displayname": "msiam_access",
"id": "ef7437e6-4f94-4a0a-a110-a439eb2aa8f7",
"isenabled": true,
"origin": "application",
"value": null
}
],
"scope": "openid profile machin:truc"
}
cognito_admin.json{
"sub": "amazon-cognito-admin",
"iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_rzhmglwjl",
"cognito:groups": ["admin", "machin:truc"],
"scope": "openid profile cog:scope"
}
cognito_machin-truc.json{
"sub": "amazon-cognito-user",
"iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_RzhmgLwjl",
"cognito:groups": ["machin:truc"],
"scope": "openid profile cog:scope"
}
以上就是使用 AAD 和 AWS Cognito 为不同端点保护 Spring Boot REST API的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号