本站资源收集于互联网,不提供软件存储服务,每天免费更新优质的软件以及学习资源!

使用AAD和AWSCognito为不同端点保护SpringBootRESTAPI

网络教程 app 1℃

使用AAD和AWSCognito为不同端点保护SpringBootRESTAPI

php小编百草为您精心撰写了一篇关于使用aad和aws cognito保护spring boot rest api的java问答文章。在这篇文章中,我们将探讨如何利用这两种身份验证服务来保护不同端点,确保您的api安全可靠。跟随我们的指引,学习如何在您的spring boot项目中实现身份验证和授权,让您的rest api更加强大和可靠。

问题内容

希望有人可以在这里帮助我,因为我在任何地方都找不到有关此主题的任何资源。

我有一个 spring boot restapi,当前配置有两种路由:1. 未经授权 2. 通过 aad/entra 的 bearer 授权

我的配置方法当前设置如下:

@overrideprotected 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>&gt; getstrings() { return responseentity.ok(…);}</list>

我们的 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 -&gt; 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 -&gt; requests .antmatchers("/api/cognito/**").fullyauthenticated());http.oauth2resourceserver().jwt([utilize aws cognito jwt validation]); } } @configuration @order(3) public static class defaultsecurityconfig extends websecurityconfigureradapter {@overrideprotected void configure(httpsecurity http) throws exception { http.csrf().disable(); http.authorizerequests(requests -&gt; 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 使用情况,但我只找到有关如何为单个租户实现该功能的信息。

如果有人已经成功实施了这个特定或类似的案例,或者可以将我推向正确的方向,我将非常感激。或者也许我的想法是完全错误的,那么请告诉我。

使用工作解决方案更新(2024 年 1 月 25 日)

感谢 @ch4mp 的回答,我已经成功了。 >工作答案

现在我的实现已经高度简化,如下所示:

应用程序.yml

: c4-soft: springaddons:oidc: ops: – iss: cognito-idp.<region>.amazonaws./<cognito-pool>authorities: – path: $.cognito:groups prefix: cognito_group_ – iss: 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</enterprise></entra></cognito-pool></region>

安全配置

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@configurationpublic 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!"); }}</string></string></string></string>

构建.gradle

implementation ‘org.springframework.boot:spring-boot-starter-oauth2-resource-server’ implementation ‘.c4-soft.springaddons:spring-addons-starter-oidc:7.3.5’

不是 spring 的官方启动器,而是 oss 实现:www./link/49844ba129a1cbc3d964703fcdb756ba

如果我遇到任何其他问题,我会再次更新,但目前它正在工作。

解决方法

我将在这里公开一个使用 my starter 的解决方案,因为它更容易。

如果您更喜欢仅使用“官方”spring boot 启动器构建安全配置,则必须使用 iss 声明提供自己的 authenticationmanagerresolver,每个身份验证管理器都有自己的身份验证转换器和自己的权限转换器来处理源声明和您想要的前缀。浏览 my tutorials 或 official documentation 以获取示例和实施提示。 This other answer 也可以提供帮助(权限映射要求完全不同,但身份验证管理器解析器类似)。

使用 boot 3.2.2 和 spring-addons

<?xml version="1.0" encoding="utf-8"?><project xmlns="maven.apache.org/pom/4.0.0" xmlns:xsi="www.w3.org/2001/xmlschema-instance" xsi:schemalocation="maven.apache.org/pom/4.0.0 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></relativepath><!– lookup parent from repository –></parent><groupid>.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>.c4-soft.springaddons</groupid><artifactid>spring-addons-starter-oidc</artifactid><version>${spring-addons.version}</version></dependency><dependency><groupid>.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@enablemethodsecuritypublic class securityconf {}

编辑以下 application.yaml 以放置您自己的发行者:

: c4-soft: springaddons:oidc: ops: – iss: cognito-idp.us-west-2.amazonaws./us-west-2_rzhmglwjl authorities: – path: $.cognito:groupsprefix: cognito_group_ – iss: sts.windows.net/0a962d63-6b23-4416-81a6-29f88c553998/ authorities: – path: $.approles.*.displaynameprefix: aad_approle_ – path: $.scopeprefix: 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. 等工具根据您自己的令牌有效负载(使用 jwt.io 等工具提取)测试路径表达式。

是的,就这么简单。不,我没有省略任何 yaml 属性或 java 配置(如果您不相信我,只需在新项目中进行测试)。

示例控制器

@restcontrollerpublic 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"); }}</string>

示例测试

@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": "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": "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": "cognito-idp.us-west-2.amazonaws./us-west-2_rzhmglwjl", "cognito:groups": ["admin", "machin:truc"], "scope": "openid profile cog:scope"}

cognito_machin-truc.json

{ "sub": "amazon-cognito-user", "iss": "cognito-idp.us-west-2.amazonaws./us-west-2_RzhmgLwjl", "cognito:groups": ["machin:truc"], "scope": "openid profile cog:scope"}

以上就是使用 AAD 和 AWS Cognito 为不同端点保护 Spring Boot REST API的详细内容,更多请关注范的资源库其它相关文章!

转载请注明:范的资源库 » 使用AAD和AWSCognito为不同端点保护SpringBootRESTAPI

喜欢 (0)