

Sécurisation de l'API REST Spring Boot pour différents points de terminaison à l'aide d'AAD et AWS Cognito
L'éditeur php Baicao a soigneusement rédigé pour vous un article de questions-réponses Java sur l'utilisation d'AAD et d'AWS Cognito pour protéger l'API REST Spring Boot. Dans cet article, nous explorerons comment tirer parti de ces deux services d'authentification pour protéger différents points de terminaison et garantir que votre API est sûre et sécurisée. Suivez notre guide et découvrez comment implémenter l'authentification et l'autorisation dans votre projet Spring Boot pour rendre votre API REST plus puissante et plus fiable.
Contenu de la question
J'espère que quelqu'un pourra m'aider ici car je ne trouve nulle part de ressources sur ce sujet.
J'ai un restapi Spring Boot, et la configuration actuelle a deux itinéraires : 1. Non autorisé 2. Autorisé via le porteur de aad/entra
Ma méthode de configuration est actuellement configurée comme suit :
@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() ); }
C'est enveloppé dans un cours qui s'étend aadresourceserverwebsecurityconfigureradapter
.
En configurant notre API de cette façon, nous sommes en mesure de sécuriser nos itinéraires comme suit :
@preauthorize("hasauthority('approle_appname.rolename')") @getmapping(value = "/some-method", produces = mediatype.application_json_value) public responseentity<list<string>> getstrings() { return responseentity.ok(...); }
Notre API devrait maintenant être étendue pour permettre à de nouveaux types d'utilisateurs d'utiliser le point de terminaison d'autorisation. Ces utilisateurs sont gérés par AWS Cognito. Comment configurer mon websecurityconfigureradapter
pour permettre à certains chemins d'être non autorisés, à certains chemins d'être protégés via aad et à certains chemins d'être protégés via aws cognito ?
Le principal problème que je semble avoir est aadresourceserverwebsecurityconfigureradapter
de configurer la validation jwt de telle manière qu'elle ne fonctionne qu'avec les porteurs fournis par Microsoft.
Idéalement, j'aimerais quelque chose comme ceci :
@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() ); } } }
Un autre problème que j'ai trouvé était aadresourceserverwebsecurityconfigureradapter
la définition automatique de tous les préfixes possibles pour les noms jwtclaim "roles" et "scp" sur "scope_" et "approle_". Idéalement, j'aimerais qu'ils soient différents pour aad et aws cognito afin que je préfixe "aad_scope_", "aad_approle_" et "cognito_group_".
J'ai trouvé des informations expliquant comment implémenter l'authentification jwt multi-tenant pour Spring Boot, mais elles utilisent toutes uniquement la base de données SQL pour implémenter l'authentification basée sur le mot de passe/l'utilisateur.
Existe-t-il un moyen de réimplémenter toute la logique aad afin de pouvoir intégrer la validation du jwt donné par aws cognito, ou existe-t-il un moyen de prendre la décision basée sur le routage ?
Je sais déjà que vous pouvez configurer l'utilisation de jwt dans la fonction httpsecurity
上使用 oauth2resourceserver()
, mais je n'ai trouvé que des informations sur la façon d'implémenter cette fonctionnalité pour un seul locataire.
Si quelqu'un a mis en œuvre avec succès ce cas spécifique ou similaire, ou peut me pousser dans la bonne direction, je lui en serais très reconnaissant. Ou peut-être que mon idée est complètement fausse, alors dites-le-moi s'il vous plaît.
Utilisation de la mise à jour des solutions de travail (25 janvier 2024)
Merci à @ch4mp pour la réponse, j'ai réussi. >Réponses de travail<
Mon implémentation est désormais très simplifiée et ressemble à ceci :
application.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
Configuration de sécurité
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 { }
Mon contrôleur ressemble maintenant à ceci :
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!"); } }
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'com.c4-soft.springaddons:spring-addons-starter-oidc:7.3.5'
Ce n'est pas le lanceur officiel du printemps, mais l'implémentation oss : https://www.php.cn/link/49844ba129a1cbc3d964703fcdb756ba
Je mettrai à jour à nouveau si je rencontre d'autres problèmes, mais pour l'instant, cela fonctionne.
Solution
Je vais exposer ici une solution en utilisant mon starter car c'est plus simple.
Si vous préférez utiliser uniquement le lanceur Spring Boot "officiel" pour créer votre configuration de sécurité, vous devez utiliser iss
声明提供自己的 authenticationmanagerresolver<httpservletrequest>
, chaque gestionnaire d'authentification a son propre convertisseur d'authentification et son propre convertisseur d'autorisations pour gérer les revendications sources et vous souhaitez le préfixe requis. Parcourez mes tutoriels ou documentation officielle pour des exemples et des conseils de mise en œuvre. Cette autre réponse peut également aider (les exigences de mappage des autorisations sont complètement différentes, mais le résolveur du gestionnaire d'authentification est similaire).
Utilisez boot 3.2.2
et 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 { }
Modifiez ce qui suit application.yaml
pour placer votre propre éditeur :
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/**
La valeur de path
ci-dessus est le chemin json. Vous pouvez utiliser des outils tels que jsonpath.com pour tester les expressions de chemin par rapport à votre propre charge utile de jeton (extraite à l'aide d'outils tels que jwt.io).
Oui, c'est aussi simple que cela. Non, je n'ai omis aucune propriété yaml ni configuration java (si vous ne me croyez pas, testez-le simplement dans un nouveau projet).
示例控制器
@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" }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Depuis sa création en 2009, Bitcoin est devenu un leader dans le monde des cryptomonnaies et son prix a connu d’énormes fluctuations. Pour fournir un aperçu historique complet, cet article compile les données sur les prix du Bitcoin de 2009 à 2025, couvrant les principaux événements du marché, les changements de sentiment du marché et les facteurs importants influençant les mouvements de prix.

Le Bitcoin, en tant que crypto-monnaie, a connu une volatilité importante sur le marché depuis sa création. Cet article fournira un aperçu du prix historique du Bitcoin depuis sa naissance pour aider les lecteurs à comprendre ses tendances de prix et ses moments clés. En analysant les données historiques sur les prix du Bitcoin, nous pouvons comprendre l'évaluation de sa valeur par le marché, les facteurs affectant ses fluctuations et fournir une base pour les décisions d'investissement futures.

Depuis sa création en 2009, le prix de Bitcoin a connu plusieurs fluctuations majeures, passant à 69 044,77 $ en novembre 2021 et tombant à 3191,22 $ en décembre 2018. En décembre 2024, le dernier prix a dépassé 100 204 $.

Prix USD Bitcoin en temps réel Facteurs qui affectent le prix du bitcoin Indicateurs pour prédire les prix des futurs bitcoins Voici quelques informations clés sur le prix du bitcoin en 2018-2024:

La méthode de personnalisation des symboles de redimension dans CSS est unifiée avec des couleurs d'arrière-plan. Dans le développement quotidien, nous rencontrons souvent des situations où nous devons personnaliser les détails de l'interface utilisateur, tels que l'ajustement ...

Comment réaliser l'effet de courbe à 45 degrés du segmenter? Dans le processus de mise en œuvre du segmentant, comment faire transformer la bordure droite en une courbe de 45 degrés lorsque vous cliquez sur le bouton gauche, et le point ...

Oui, la production de pages H5 est une méthode de mise en œuvre importante pour le développement frontal, impliquant des technologies de base telles que HTML, CSS et JavaScript. Les développeurs construisent des pages H5 dynamiques et puissantes en combinant intelligemment ces technologies, telles que l'utilisation du & lt; Canvas & gt; Tag pour dessiner des graphiques ou utiliser JavaScript pour contrôler le comportement d'interaction.

La communauté technique de questions-réponses à l'ère Chatgpt: Stratégie de réponse de SegmentFault StackOverflow ...