1. 概要

このチュートリアルでは、セキュリティに対するSpring Bootの意見のあるアプローチを見ていきます。

簡単に言えば、デフォルトのセキュリティ構成と、必要に応じてそれを無効化またはカスタマイズする方法に焦点を当てます。

2. デフォルトのセキュリティ設定

Spring Bootアプリケーションにセキュリティを追加するには、セキュリティスターター依存関係を追加する必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

これには、初期/デフォルトのセキュリティ構成を含むSecurityAutoConfigurationクラスも含まれます。

プロジェクトがすでに親としてBootを使用していることを前提として、ここでバージョンを指定しなかったことに注意してください。

デフォルトでは、認証はアプリケーションに対して有効になっています。 また、コンテンツネゴシエーションは、basicとformLoginのどちらを使用するかを決定するために使用されます。

いくつかの事前定義されたプロパティがあります。

spring.security.user.name
spring.security.user.password

事前定義されたプロパティspring.security.user.passwordを使用してパスワードを構成せずにアプリケーションを起動すると、デフォルトのパスワードがランダムに生成され、コンソールログに出力されます。

Using default security password: c8be15de-4488-4490-9dc6-fab3f91435c6

その他のデフォルトについては、 Spring Boot Common ApplicationPropertiesリファレンスページのセキュリティプロパティのセクションを参照してください。

3. 自動構成の無効化

セキュリティの自動構成を破棄して独自の構成を追加するには、SecurityAutoConfigurationクラスを除外する必要があります。

これは、単純な除外によって行うことができます。

@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class SpringBootSecurityApplication {

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

または、application.propertiesファイルに構成を追加することもできます。

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration

ただし、この設定では不十分な場合もあります。

たとえば、ほとんどすべてのSpring Bootアプリケーションは、クラスパスのActuatorで起動されます。 これにより、別の自動構成クラスが除外したクラスを必要とするため、問題が発生します。したがって、アプリケーションは起動に失敗します。

この問題を修正するには、そのクラスを除外する必要があります。 また、アクチュエータの状況に固有に、ManagementWebSecurityAutoConfigurationも除外する必要があります。

3.1. セキュリティ自動構成の無効化と超過

自動構成を無効にすることとそれを超えることには大きな違いがあります。

これを無効にすることは、SpringSecurityの依存関係とセットアップ全体を最初から追加するのと同じです。 これは、いくつかの場合に役立ちます。

  1. アプリケーションセキュリティとカスタムセキュリティプロバイダーの統合
  2. 既存のセキュリティ設定を備えたレガシーSpringアプリケーションのSpringBootへの移行

ただし、ほとんどの場合、セキュリティの自動構成を完全に無効にする必要はありません。

これは、Spring Bootが、新しい/カスタム構成クラスを追加することにより、自動構成されたセキュリティを超えることができるように構成されているためです。 ニーズを満たすために既存のセキュリティ設定をカスタマイズしているだけなので、これは通常簡単です。

4. SpringBootSecurityの構成

セキュリティの自動構成を無効にするパスを選択した場合は、当然、独自の構成を提供する必要があります。

前に説明したように、これはデフォルトのセキュリティ構成です。 次に、プロパティファイルを変更してカスタマイズします。

たとえば、独自のパスワードを追加することで、デフォルトのパスワードを上書きできます。

spring.security.user.password=password

たとえば、複数のユーザーとロールを使用する、より柔軟な構成が必要な場合は、完全な@Configurationクラスを使用する必要があります。

@Configuration
@EnableWebSecurity
public class BasicConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	PasswordEncoder encoder = 
          PasswordEncoderFactories.createDelegatingPasswordEncoder();
    	auth
          .inMemoryAuthentication()
          .withUser("user")
          .password(encoder.encode("password"))
          .roles("USER")
          .and()
          .withUser("admin")
          .password(encoder.encode("admin"))
          .roles("USER", "ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic();
    }
}

@EnableWebSecurity アノテーションは、デフォルトのセキュリティ構成を無効にする場合に重要です。

欠落している場合、アプリケーションは起動に失敗します。 したがって、 WebSecurityConfigurerAdapter を使用してデフォルトの動作をオーバーライドする場合にのみ、アノテーションはオプションです。

また、Spring Boot 2を使用する場合は、 PasswordEncoderを使用してパスワードを設定する必要があることに注意してください。詳細については、 Spring Security5のデフォルトパスワードエンコーダーに関するガイドを参照してください。

次に、いくつかのクイックライブテストを使用して、セキュリティ構成が正しく適用されることを確認する必要があります。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class BasicConfigurationIntegrationTest {

    TestRestTemplate restTemplate;
    URL base;
    @LocalServerPort int port;

    @Before
    public void setUp() throws MalformedURLException {
        restTemplate = new TestRestTemplate("user", "password");
        base = new URL("http://localhost:" + port);
    }

    @Test
    public void whenLoggedUserRequestsHomePage_ThenSuccess()
     throws IllegalStateException, IOException {
        ResponseEntity<String> response =
          restTemplate.getForEntity(base.toString(), String.class);
 
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertTrue(response.getBody().contains("Baeldung"));
    }

    @Test
    public void whenUserWithWrongCredentials_thenUnauthorizedPage() 
      throws Exception {
 
        restTemplate = new TestRestTemplate("user", "wrongpassword");
        ResponseEntity<String> response =
          restTemplate.getForEntity(base.toString(), String.class);
 
        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
        assertTrue(response.getBody().contains("Unauthorized"));
    }
}

SpringSecurityは実際にはSpringBootSecurityの背後にあるため、これを使用して実行できるセキュリティ構成、またはこれがサポートする統合をSpringBootに実装することもできます。

5. Spring Boot OAuth2自動構成(レガシースタックを使用)

Spring Bootには、OAuth2専用の自動構成サポートがあります。

SpringBoot1.xに付属していたSpringSecurity OAuth サポートは、 Spring Security 5 にバンドルされているファーストクラスのOAuthサポートの代わりに、以降のブートバージョンで削除されました。 次のセクションでその使用方法を説明します。

レガシースタック(Spring Security OAuthを使用)の場合、最初にMaven依存関係を追加して、アプリケーションのセットアップを開始する必要があります。

<dependency>
   <groupId>org.springframework.security.oauth</groupId>
   <artifactId>spring-security-oauth2</artifactId>
</dependency>

この依存関係には、OAuth2AutoConfigurationクラスで定義された自動構成メカニズムをトリガーできる一連のクラスが含まれます。

現在、アプリケーションの範囲に応じて、続行するための複数の選択肢があります。

5.1. OAuth2認証サーバーの自動構成

アプリケーションをOAuth2プロバイダーにする場合は、@EnableAuthorizationServerを使用できます。

起動時に、自動構成クラスが承認サーバーのクライアントIDとクライアントシークレットを生成し、もちろん基本認証用のランダムパスワードを生成することがログに表示されます。

Using default security password: a81cb256-f243-40c0-a585-81ce1b952a98
security.oauth2.client.client-id = 39d2835b-1f87-4a77-9798-e2975f36972e
security.oauth2.client.client-secret = f1463f8b-0791-46fe-9269-521b86c55b71

これらの資格情報は、アクセストークンを取得するために使用できます。

curl -X POST -u 39d2835b-1f87-4a77-9798-e2975f36972e:f1463f8b-0791-46fe-9269-521b86c55b71 \
 -d grant_type=client_credentials 
 -d username=user 
 -d password=a81cb256-f243-40c0-a585-81ce1b952a98 \
 -d scope=write  http://localhost:8080/oauth/token

私たちの他の記事は、この主題に関する詳細を提供します。

5.2. その他のSpringBootOAuth2自動構成設定

SpringBootOAuth2でカバーされる他のいくつかのユースケースがあります。

  1. リソースサーバー @EnableResourceServer
  2. クライアントアプリケーション @EnableOAuth2Ssoまたは@EnableOAuth2Client

アプリケーションをこれらのタイプのいずれかにする必要がある場合は、リンクで詳しく説明されているように、アプリケーションのプロパティにいくつかの構成を追加する必要があります。

OAuth2固有のすべてのプロパティは、 Spring Boot Common ApplicationPropertiesにあります。

6. Spring Boot OAuth2自動構成(新しいスタックを使用)

新しいスタックを使用するには、構成するもの(承認サーバー、リソースサーバー、またはクライアントアプリケーション)に基づいて依存関係を追加する必要があります。

それらを一つずつ見ていきましょう。

6.1. OAuth2認証サーバーのサポート

これまで見てきたように、Spring Security OAuthスタックは、承認サーバーをSpringアプリケーションとしてセットアップする可能性を提供しました。 ただし、このプロジェクトは廃止されており、Springは現在独自の承認サーバーをサポートしていません。 代わりに、Okta、Keycloak、ForgeRockなどの既存の定評のあるプロバイダーを使用することをお勧めします。

ただし、Spring Bootを使用すると、このようなプロバイダーを簡単に構成できます。 Keycloakの設定例については、SpringBootでKeycloakを使用するためのクイックガイドまたはSpringBootアプリケーションに埋め込まれたKeycloakのいずれかを参照できます。

6.2. OAuth2リソースサーバーのサポート

リソースサーバーのサポートを含めるには、次の依存関係を追加する必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>    
</dependency>

最新のバージョン情報については、 MavenCentralにアクセスしてください。

さらに、セキュリティ構成に、 oauth2ResourceServer()DSLを含める必要があります。

@Configuration
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          ...
          .oauth2ResourceServer(oauth2 -> oauth2.jwt());
          ...
	}
}

Spring Security5を備えたOAuth2.0リソースサーバーは、このトピックの詳細を提供します。

6.3. OAuth2クライアントのサポート

リソースサーバーの構成方法と同様に、クライアントアプリケーションにも独自の依存関係とDSLが必要です。

OAuth2クライアントサポートの特定の依存関係は次のとおりです。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

最新バージョンはMavenCentralにあります。

Spring Security 5は、 oath2Login()DSLを介したファーストクラスのログインサポートも提供します。

新しいスタックでのSSOサポートの詳細については、記事 Spring SecurityOAuth2を使用したシンプルなシングルサインオンを参照してください。

7. SpringBoot2のセキュリティとSpringBoot1のセキュリティ

Spring Boot 1と比較して、 SpringBoot2は自動構成を大幅に簡素化しました。

Spring Boot 2では、独自のセキュリティ構成が必要な場合は、カスタム WebSecurityConfigurerAdapterを追加するだけです。これにより、デフォルトの自動構成が無効になり、カスタムセキュリティ構成が有効になります。

Spring Boot 2は、SpringSecurityのデフォルトのほとんども使用します。 そのため、 Spring Boot 1でデフォルトで保護されていなかったエンドポイントの一部が、デフォルトで保護されるようになりました。

これらのエンドポイントには、/ css / **、/ js / **、/ images / **、/ webjars / **、/ **/favicon.icoなどの静的リソースとエラーエンドポイントが含まれます。 これらのエンドポイントへの認証されていないアクセスを許可する必要がある場合は、それを明示的に構成できます。

セキュリティ関連の構成を簡素化するために、 SpringBoot2はこれらのSpringBoot1プロパティを削除しました。

security.basic.authorize-mode
security.basic.enabled
security.basic.path
security.basic.realm
security.enable-csrf
security.headers.cache
security.headers.content-security-policy
security.headers.content-security-policy-mode
security.headers.content-type
security.headers.frame
security.headers.hsts
security.headers.xss
security.ignored
security.require-ssl
security.sessions

8. 結論

この記事では、SpringBootによって提供されるデフォルトのセキュリティ構成に焦点を当てました。 セキュリティ自動構成メカニズムを無効化またはオーバーライドする方法を確認しました。 次に、新しいセキュリティ構成を適用する方法を確認しました。

OAuth2のソースコードは、OAuth2GitHubリポジトリのlegacyおよびnewスタックにあります。 残りのコードは、GitHubにあります。