搜尋
首頁Java使用 AAD 和 AWS Cognito 為不同端點保護 Spring Boot REST API

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 使用情況,但我只找到有關如何為單一租用戶實現該功能的資訊。

如果有人已經成功實施了這個特定或類似的案例,或者可以將我推向正確的方向,我將非常感激。 或者也許我的想法是完全錯誤的,那麼請告訴我。

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

感謝 @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></httpservletrequest>,每個驗證管理器都有自己的身份驗證轉換器和自己的權限轉換器來處理來源聲明和您想要的前綴。瀏覽 my tutorialsofficial documentation 以取得範例和實作提示。 This other answer 也可以提供協助(權限對應要求完全不同,但驗證管理器解析器類似)。

使用 boot 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中文網其他相關文章!

陳述
本文轉載於:stackoverflow。如有侵權,請聯絡admin@php.cn刪除
Linux下查看内存使用情况方法总结Linux下查看内存使用情况方法总结Feb 05, 2024 am 11:45 AM

Q:我有一个问题,我想要监视Linux系统的内存使用情况。在Linux下有哪些可用的视图或命令行工具可以使用呢?A:在Linux系统中,有多种方法可以监视内存使用情况。下面是一些通过视图工具或命令行来查看内存使用情况的方法。/proc/meminfo:最简单的方法是查看/proc/meminfo文件。这个虚拟文件会动态更新,并提供了关于内存使用情况的详细信息。它列出了各种内存指标,可以满足你对内存使用情况的大部分需求。另外,你还可以通过/proc//statm和/proc//status来查看进

Linux 上的最佳白板应用程序Linux 上的最佳白板应用程序Feb 05, 2024 pm 12:48 PM

“我们将介绍几款适用于Linux系统的白板应用程序,相信这些信息对您会非常有帮助。请继续阅读!”一般来说,数字白板是一种用于大型互动显示面板的工具,常见的设备类型包括平板电脑、大屏手机、触控笔记本和表面显示设备等。当教师使用白板时,您可以使用触控笔、手写笔、手指甚至鼠标在设备屏幕上进行绘画、书写或操作元素。这意味着您可以在白板上拖动、点击、删除和绘画,就像在纸上使用笔一样。然而,要实现这一切,需要有一款软件来支持这些功能,并实现触控和显示之间的精细协调。目前市面上有许多商业应用可以完成这项工作。

​揭秘NVIDIA大模型推理框架:TensorRT-LLM​揭秘NVIDIA大模型推理框架:TensorRT-LLMFeb 01, 2024 pm 05:24 PM

一、TensorRT-LLM的产品定位TensorRT-LLM是NVIDIA为大型语言模型(LLM)开发的可扩展推理方案。它基于TensorRT深度学习编译框架构建、编译和执行计算图,并借鉴了FastTransformer中高效的Kernels实现。此外,它还利用NCCL实现设备间的通信。开发者可以根据技术发展和需求差异,定制算子以满足特定需求,例如基于cutlass开发定制的GEMM。TensorRT-LLM是NVIDIA官方推理方案,致力于提供高性能并不断完善其实用性。TensorRT-LL

ZR币升值空间大吗? ZR币在哪里购买交易?ZR币升值空间大吗? ZR币在哪里购买交易?Feb 01, 2024 pm 08:09 PM

ZRX(0x)是一个基于以太坊区块链的开放协议,用于实现分布式交易和去中心化交易所(DEX)功能。作为0x协议的原生代币,ZRX可用于支付交易费用、治理协议变更和获取平台优惠。1.ZRX币升值空间展望:从技术角度来看,ZRX作为0x协议的核心代币,在去中心化交易所的应用逐渐增多,市场对其认可度也在增加。以下是几个关键因素,有助于提升ZRX币的价值空间:市场需求潜力大、社区活跃度高、开发者生态繁荣等。这些因素共同促进了ZRX的广泛应用和使用,进而推动了其市场价格的上升。市场需求的增长潜力,意味着更

Linux字节对齐的那些事Linux字节对齐的那些事Feb 05, 2024 am 11:06 AM

最近,我正在进行一个项目,遇到了一个问题。在ARM上运行的ThreadX与DSP通信时采用了消息队列的方式传递消息(最终实现使用了中断和共享内存的方法)。然而,在实际的操作过程中,发现ThreadX经常崩溃。经过排查,发现问题出在传递消息的结构体没有考虑字节对齐的问题上。我想顺便整理一下关于C语言中字节对齐的问题,并与大家分享。一、概念字节对齐与数据在内存中的位置有关。如果一个变量的内存地址恰好是它长度的整数倍,那么它就被称为自然对齐。例如,在32位CPU下,假设一个整型变量的地址为0x0000

手把手教你构建linux rootfs手把手教你构建linux rootfsFeb 05, 2024 pm 03:51 PM

busybox概述众所周知,在Linux环境下,一切皆文件,文件可以表示一切。而文件系统则是这些普通组件的集合。在嵌入式领域中,常常使用基于busybox构建的rootfs来构建文件系统。busybox诞生至今已有近20年的历史,如今已成为嵌入式行业中主流的rootfs构建工具。busybox的代码是完全开源的。你可以进入官方网站,点击”GetBusyBox”下面的”DownloadSource”进入源码下载界面。“官方网站链接:https://busybox.net/”2.busybox的配置

BOSS直聘怎么创建多个简历BOSS直聘怎么创建多个简历Feb 05, 2024 pm 02:18 PM

BOSS直聘怎么创建多个简历?BOSS直聘是很多小伙伴找工作的一大招聘平台,为用户们提供了非常多便利的求职服务。各位在使用BOSS直聘的时候,可以创建多个不同的简历,以便投送到不同的工作岗位上,获取到更高成功率的求职操作,各位如果对此感兴趣的话,就随小编一起来看看BOSS直聘双简历创建教程吧。BOSS直聘怎么创建多个简历1.登录Boss直聘:在您的电脑或手机上,登录您的Boss直聘账户。2.进入简历管理:在Boss直聘首页,点击“简历管理”,进入简历管理页面。3.创建新简历:在简历管理页面,点击

幻兽帕鲁开局攻略幻兽帕鲁开局攻略Feb 01, 2024 pm 05:36 PM

幻兽帕鲁游戏开局就可以拿三个宝箱和两个宠物蛋,拿完以后就可以开始建家了,建家的地址一定要选好,要不然开局会发现自己的家没有了,然后就是捕捉一直适合自己的帕鲁,作为自己的伙伴或者打工人即可。

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。