[JAVA] Créez un serveur Spring Cloud Config en toute sécurité avec Spring Boot 2.0

Que faire cette fois

スクリーンショット 2018-03-09 14.56.50.png

L'authentification BASIC est appliquée entre curl et Client et entre Client et Config Server. À l'origine, OAuth 2.0 est probablement meilleur, mais c'est une autre opportunité.

L'exemple de code est téléchargé sur GitHub.

environnement

Au moment de la rédaction de cet article, Spring Cloud Finchley n'a pas encore été officiellement publié. Veuillez noter que les spécifications peuvent changer à l'avenir.

Pour le serveur de configuration lui-même, voir Blog de Maki. Cependant, veuillez noter qu'il s'agit d'un article avant la sortie officielle, il y a donc quelques différences par rapport à l'actuel.

Créer un référentiel de configuration

Vous pouvez utiliser Git ou SVN comme référentiel. Cette fois, j'utiliserai GitHub. Cliquez ici pour URL-> https://github.com/MasatoshiTada/app-config Veuillez fourcher et utiliser!

application.properties Ce paramètre est utilisé pour toutes les applications et tous les profils.

application.properties


message=Hello application!
common=common

application-xxx.properties Ce paramètre est utilisé par toutes les applications, mais uniquement par un profil spécifique ("xxx" est le nom du profil).

application-dev.properties


message=Hello application-dev!
common=common-dev

application-qa.properties


message=Hello application-qa!
common=common-qa

client.properties Ce paramètre est utilisé pour tous les profils uniquement dans l'application dont le nom est "client".

client.properties


message=Hello client!
server.port=8081
#Utilisé pour actualiser les paramètres/Activer le point de terminaison d'actualisation
management.endpoints.web.exposure.include=refresh
#Définissez le niveau de journalisation de Spring Security à tracer pour faciliter la visualisation de l'exécution interne.
logging.level.org.springframework.security=trace

La troisième ligne, management.endpoints.web.exposure.include = refresh, est un nouveau paramètre de Spring Boot 2.0. Dans Spring Boot 2.0, seuls les points de terminaison décrits dans ce paramètre sont activés (plusieurs spécifications peuvent être spécifiées séparées par des virgules).

client-xxx.properties Ce paramètre n'est utilisé que pour des profils spécifiques uniquement dans les applications dont le nom est "client" ("xxx" est le nom du profil).

client-dev.properties


message=Hello client-dev!
server.port=8082

client-qa.properties


message=Hello client-qa!
server.port=8083

foo.properties Ce paramètre est utilisé pour tous les profils uniquement dans les applications dont le nom est "foo".

foo.properties


message=Hello foo!
server.port=9001

foo-xxx.properties Ce paramètre n'est utilisé que pour des profils spécifiques uniquement dans les applications dont le nom est "foo" ("xxx" est le nom du profil).

foo-dev.properties


message=Hello foo-dev!
server.port=9002

foo-qa.properties


message=Hello foo-qa!
server.port=9003

Définition de la priorité

Si un autre fichier a un paramètre avec le même nom, il sera priorisé dans l'ordre suivant (le plus élevé sera priorisé).

  1. Nom de l'application-Nom du profil.properties
  2. Nom de l'application.properties
  3. nom du profil d'application.properties
  4. application.properties

Créer un serveur de configuration

(1) Créez un modèle avec Spring Initializr. Décidez "Group" et "Artifact" de manière appropriée, et ajoutez "Config Server" et "Security" dans "Dependencies".

スクリーンショット 2018-03-09 13.08.27.png

(2) Ajoutez @ EnableConfigServer à la classe qui a la méthode main ().

@SpringBootApplication
@EnableConfigServer //Joindre ceci
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

(3) Créez une classe Java Config pour Spring Security. Créez un utilisateur avec n'importe quel nom d'utilisateur et mot de passe et activez l'authentification BASIC.

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // "client"Créer un utilisateur
        //N'utilisez pas NoOpPasswordEncoder en production, utilisez plutôt BCryptPasswordEncoder
        auth.inMemoryAuthentication()
                .passwordEncoder(NoOpPasswordEncoder.getInstance())
                .withUser("client").password("password").roles("CLIENT");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Activez l'authentification BASIC afin que toutes les URL doivent être authentifiées avant de pouvoir y accéder
        http.httpBasic();
        http.authorizeRequests()
                .anyRequest().authenticated();
    }
}

Comme mentionné dans les commentaires, NoOpPasswordEncoder n'encode pas du tout les mots de passe et ne doit pas être utilisé en production (déjà obsolète dans Spring Security 5). Cette fois, je l'utilise uniquement pour apprendre.

(4) Décrivez les paramètres dans application.properties.

#URL du référentiel Git
spring.cloud.config.server.git.uri=https://github.com/MasatoshiTada/app-config.git

#Numéro de port de ce serveur de configuration
server.port=8888

Faire un client

(1) Créez un modèle avec Spring Initializr. Choisissez "Group" et "Artifact" de manière appropriée et ajoutez "Web", "Config Client", "Actuator" et "Security" dans "Dependencies".

スクリーンショット 2018-03-09 13.09.59.png

(2) Créez une classe Java Config pour Spring Security. Créez deux utilisateurs avec n'importe quel nom d'utilisateur et mot de passe (séparez les rôles et donnez-leur n'importe quel nom de rôle).

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // "ACTUATOR"Quand"USER"Quandいう2つのロールのユーザーを作る
        //N'utilisez pas NoOpPasswordEncoder en production!
        auth.inMemoryAuthentication()
                .passwordEncoder(NoOpPasswordEncoder.getInstance())
                .withUser("actuator").password("password").roles("ACTUATOR").and()
                .withUser("user").password("password").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Activer l'authentification BASIC
        http.httpBasic();
        //Les extrémités de l'actionneur ne sont accessibles que par le rôle ACTUATOR,
        //Les autres sont accessibles par n'importe quel rôle tant que vous êtes connecté
        http.authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
                .anyRequest().authenticated();

        //Ne désactivez pas CSRF en production!
        http.csrf().disable();
    }
}

Cette fois, nous avons désactivé CSRF pour éviter de rendre l'échantillon trop compliqué. Veuillez ne pas le désactiver dans l'environnement de production et obtenir un jeton par certains moyens avant d'accéder avec curl.

(3) Décrivez les paramètres dans bootstrap.properties.

#Nom de l'application pour ce client
spring.application.name=client

#URL du serveur de configuration
spring.cloud.config.uri=http://localhost:8888/

#Nom d'utilisateur et mot de passe pour accéder à Config Server
#(Créé avec Java Config de Config Server)
spring.cloud.config.username=client
spring.cloud.config.password=password

bootstrap.properties décrit les paramètres de démarrage et n'est utilisé que dans l'environnement Spring Cloud.

(4) Créez un contrôleur approprié qui renvoie la valeur obtenue à partir de Config Server. Ajoutez @ RefreshScope à la classe.

@RefreshScope  // "POST /actuator/refresh"Détruira l'instance de cette classe
@RestController
@RequestMapping("/hello")
public class HelloController {

    private final String message;
    private final String common;

    //Obtenez la valeur obtenue à partir de Config Server avec le constructeur
    public HelloController(@Value("${message}") String message, @Value("${common}") String common) {
        this.message = message;
        this.common = common;
    }

    @GetMapping
    public Map<String, String> hello() {
        HashMap<String, String> map = new HashMap<>();
        map.put("message", message);
        map.put("common", common);
        return map;
    }
}

Démarrez Config Server et obtenez les paramètres avec curl

(1) Démarrez uniquement Config Server. (2) Vous pouvez obtenir la valeur de application.properties en accédant à / application / default.

$ curl -X GET -u client:password http://localhost:8888/application/default | jq
{
  "name": "application",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": "e87b3c3ff0239394963e3bddf0a2982db5064339",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application.properties",
      "source": {
        "message": "Hello application!",
        "common": "common"
      }
    }
  ]
}

(2) Vous pouvez obtenir les valeurs de application.properties et application-dev.properties en accédant à / application / dev.

$ curl -X GET -u client:password http://localhost:8888/application/dev | jq
{
  "name": "application",
  "profiles": [
    "dev"
  ],
  "label": null,
  "version": "e87b3c3ff0239394963e3bddf0a2982db5064339",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application-dev.properties",
      "source": {
        "message": "Hello application-dev!",
        "common": "common-dev"
      }
    },
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application.properties",
      "source": {
        "message": "Hello application!",
        "common": "common"
      }
    }
  ]
}

Bien que cela ne soit pas décrit, vous pouvez obtenir les valeurs de application.properties et application-qa.properties en accédant à / application / qa.

(3) Vous pouvez obtenir les valeurs de application.properties et client.properties en accédant à / client / default.

$ curl -X GET -u client:password http://localhost:8888/client/default | jq
{
  "name": "client",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": "e87b3c3ff0239394963e3bddf0a2982db5064339",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/client.properties",
      "source": {
        "message": "Hello client!",
        "server.port": "8081",
        "management.endpoints.web.exposure.include": "refresh",
        "logging.level.org.springframework.security": "trace"
      }
    },
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application.properties",
      "source": {
        "message": "Hello application!",
        "common": "common"
      }
    }
  ]
}

Bien que cela ne soit pas décrit, vous pouvez obtenir les valeurs de application.properties et foo.properties en accédant à / foo / default.

(4) En accédant à / client / dev, vous pouvez obtenir les valeurs de application.properties, application-dev.properties, client.properties, client-dev.properties.

$ curl -X GET -u client:password http://localhost:8888/client/dev | jq
{
  "name": "client",
  "profiles": [
    "dev"
  ],
  "label": null,
  "version": "e87b3c3ff0239394963e3bddf0a2982db5064339",
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/client-dev.properties",
      "source": {
        "message": "Hello client-dev!",
        "server.port": "8082"
      }
    },
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application-dev.properties",
      "source": {
        "message": "Hello application-dev!",
        "common": "common-dev"
      }
    },
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/client.properties",
      "source": {
        "message": "Hello client!",
        "server.port": "8081",
        "management.endpoints.web.exposure.include": "refresh",
        "logging.level.org.springframework.security": "trace"
      }
    },
    {
      "name": "https://github.com/MasatoshiTada/app-config.git/application.properties",
      "source": {
        "message": "Hello application!",
        "common": "common"
      }
    }
  ]
}

Non listé,

  • Vous pouvez obtenir les valeurs de application.properties, application-qa.properties, client.properties, client-qa.properties en accédant à / client / qa.
  • Vous pouvez obtenir les valeurs de application.properties, application-dev.properties, foo.properties et foo-dev.properties en accédant à / foo / dev.
  • Vous pouvez obtenir les valeurs de application.properties, application-qa.properties, foo.properties et foo-qa.properties en accédant à / foo / qa.

Gardez le serveur de configuration en marche après les vérifications ci-dessus.

Obtenez de la valeur du client

(1) Démarrez le client sans spécifier de profil. (2) Au démarrage, le client accède à Config Server avec l'URL essayée dans le chapitre précédent en fonction du nom de l'application spécifié dans spring.application.name et du nom du profil en cours d'exécution (dans ce cas, / client. / default). De plus, l'authentification BASIC est utilisée pour cet accès (nom d'utilisateur «client», mot de passe «mot de passe»). (3) Accédez à localhost: 8081 / hello avec curl.

$ curl -X GET -u user:password http://localhost:8081/hello | jq
{
  "common": "common",
  "message": "Hello client!"
}

"common" est la valeur de application.properties. "message" est également défini dans application.properties, mais la valeur de client.properties est utilisée à partir de la règle de priorité. Le numéro de port 8081 en cours d'exécution est également la valeur de client.properties.

(4) Arrêtez le client une fois et redémarrez-le avec le profil de développement. Le profil est spécifié par un argument de ligne de commande avec "-" (en outre, il peut être spécifié par des variables d'environnement, des propriétés système JVM, etc.)

client $ mvn clean package
client $ java -jar target/client-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
client $ curl -X GET -u user:password http://localhost:8082/hello | jq
{
  "common": "common-dev",
  "message": "Hello client-dev!"
}

"common" est la valeur de application-dev.properties. "message" est la valeur de client-dev.properties. Le numéro de port 8082 en cours d'exécution est également la valeur de client-dev.properties.

Changer la valeur pendant l'exécution

(1) Arrêtez le client en cours d'exécution et redémarrez-le sans spécifier de profil. (2) Accédez au point de terminaison / hello avec curl. La valeur du message est "Hello client!".

$ curl -X GET -u user:password http://localhost:8081/hello | jq
{
  "common": "common",
  "message": "Hello client!"
}

(3) Sur GitHub, réécrivez la valeur du message dans client.properties.

message=Hello client!!!!!!!!!!!!!!!!!!!!!!!!!

(4) Accédez à nouveau au point de terminaison / hello avec curl. La valeur du message reste "Bonjour client!" Et n'a pas changé. En effet, la valeur modifiée dans GitHub n'a pas encore été reflétée côté client.

$ curl -X GET -u user:password http://localhost:8081/hello | jq
{
  "common": "common",
  "message": "Hello client!"
}

(5) Accéder à / actionneur / rafraîchir avec curl. Le client accède ensuite au serveur de configuration, qui récupère la valeur de GitHub et la transmet au client.

$ curl -X POST -u actuator:password http://localhost:8081/actuator/refresh | jq
[
  "config.client.version",
  "message"
]

Notez que le nom d'utilisateur spécifié avec -u est ʻactuator. Il s'agit d'un utilisateur créé dans Java Config sur le client et d'un utilisateur dans le rôle ʻACTUATOR qui a l'autorisation d'accéder/ actuator / **.

(6) Une fois rafraîchi, le bean avec @ RefreshScope attaché (cette fois HelloController) est détruit. L'instance est recréée la première fois que le bean est nécessaire après une actualisation (dans ce cas, lorsque curl accède à / hello), et les nouveaux paramètres après la modification sont utilisés.

$ curl -X GET -u user:password http://localhost:8081/hello | jq
{
  "common": "common",
  "message": "Hello client!!!!!!!!!!!!!!!!!!!!!!!!!"
}

Recommended Posts

Créez un serveur Spring Cloud Config en toute sécurité avec Spring Boot 2.0
Créer un serveur API Web avec Spring Boot
Créer un micro service avec Spring Boot
Créez un site de démonstration simple avec Spring Security avec Spring Boot 2.1
Google Cloud Platform avec Spring Boot 2.0.0
Obtenez une authentification BASIC avec Spring Boot + Spring Security
Créez un site Web avec Spring Boot + Gradle (jdk1.8.x)
Créez une application de recherche simple avec Spring Boot
Hash des mots de passe avec Spring Boot + Spring Security (avec sel, avec étirement)
Essayez l'authentification LDAP avec Spring Security (Spring Boot) + OpenLDAP
Créez une application CRUD avec Spring Boot 2 + Thymeleaf + MyBatis
Créer un environnement Spring Boot avec Windows + VS Code
[Introduction à Spring Boot] Fonction d'authentification avec Spring Security
Créer un environnement de développement Spring Boot avec docker
Mémo d'utilisation de Spring Security: coopération avec Spring MVC et Boot
Implémentez une API Rest simple avec Spring Security avec Spring Boot 2.0
Créer Restapi avec Spring Boot (jusqu'à l'exécution de l'application)
Générer un code à barres avec Spring Boot
Hello World avec Spring Boot
Configuration Java avec Spring MVC
Démarrez avec Spring Boot
Bonjour tout le monde avec Spring Boot!
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Fonction de connexion avec Spring Security
Spring Boot à partir de Docker
Hello World avec Spring Boot
Définir des cookies avec Spring Boot
Utiliser Spring JDBC avec Spring Boot
Ajouter un module avec Spring Boot
Premiers pas avec Spring Boot
Essayez d'utiliser Spring Boot Security
Envoyer du courrier avec Spring Boot
Utiliser l'authentification de base avec Spring Boot
Mise en œuvre de la fonction d'authentification avec Spring Security ②
gRPC sur Spring Boot avec grpc-spring-boot-starter
Déploiement à chaud avec le développement Spring Boot
Tutoriel Spring Boot à l'aide de l'authentification Spring Security
Programmation Spring Boot avec VS Code
Jusqu'à "Hello World" avec Spring Boot
Créer une application d'enquête avec Spring Boot
Mise en œuvre de la fonction d'authentification avec Spring Security ①
Obtenez des résultats de validation avec Spring Boot
Authentification Oauth2 avec Spring Cloud Gateway
(Intellij) Hello World avec Spring Boot
J'ai essayé GraphQL avec Spring Boot
[Java] Intégration LINE avec Spring Boot
À partir de Spring Boot 0. Utilisez Spring CLI
J'ai essayé Flyway avec Spring Boot
Implémentez un serveur API Web REST simple avec Spring Boot + MySQL
J'ai essayé d'implémenter un client OAuth avec Spring Boot / Security (connexion LINE)
Partie 1: Essayez d'utiliser la connexion OAuth 2.0 prise en charge par Spring Security 5 avec Spring Boot
Comment créer votre propre contrôleur correspondant à / error avec Spring Boot
Traitement lors du démarrage d'une application avec Spring Boot
Création d'un environnement de développement Spring Boot dans Vagrant
Comment lire le corps de la requête plusieurs fois avec Spring Boot + Spring Security
Créez un projet de développement d'application Spring Boot avec la commande cURL + tar
Hello World avec Eclipse + Spring Boot + Maven