Spring Securityの基本認証

1概要

このチュートリアルでは、 Spring を使った基本認証の設定、設定、カスタマイズの方法を説明します。/spring-mvc-tutorial[Spring MVCの例]の上に構築し、Spring Securityが提供するBasic Authメカニズムを使ってMVCアプリケーションのUIを保護します。

2 Springのセキュリティ設定

Javaセキュリティを使用してSpring Securityを設定できます。

@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyBasicAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
          .withUser("user1").password(passwordEncoder().encode("user1Pass"))
          .authorities("ROLE__USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/securityNone").permitAll()
          .anyRequest().authenticated()
          .and()
          .httpBasic()
          .authenticationEntryPoint(authenticationEntryPoint);

        http.addFilterAfter(new CustomFilter(),
          BasicAuthenticationFilter.class);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

ここでは、 WebSecurityConfigurerAdapterを拡張するクラスの configure() メソッド内で、 httpBasic()__要素を使用して基本認証を定義しています

XMLを使用しても同じことが実現できます。

<http pattern="/securityNone" security="none"/>
<http use-expressions="true">
    <intercept-url pattern="/** ** " access="isAuthenticated()"/>
    <http-basic/>
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="{noop}user1Pass" authorities="ROLE__USER"/>
        </user-service>
    </authentication-provider>
</authentication-manager>

ここで重要なのは、設定のメインの <http> 要素内の <http-basic> 要素です - これはアプリケーション全体の基本認証を有効にするのに十分です。認証マネージャはこのチュートリアルの中心ではないので、プレーンテキストで定義されたユーザとパスワードを持つインメモリマネージャを使用しています。

Spring Securityを有効にするWebアプリケーションの web.xml は、リンク/spring-security-login#web__xml[Spring Logout tutorial]ですでに説明されています。

3保護されたアプリケーションを使用する

curl コマンドは、セキュリティで保護されたアプリケーションを利用するための便利なツールです。

まず、セキュリティ情報を指定せずに /homepage.html をリクエストしてみましょう。

curl -i http://localhost:8080/spring-security-rest-basic-auth/api/foos/1

予想される 401 Unauthorized とhttp://tools.ietf.org/html/rfc1945#section-10.16[認証の課題]を取り戻します。

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E5A8D3C16B65A0A007CFAACAEEE6916B; Path=/spring-security-mvc-basic-auth/; HttpOnly
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Wed, 29 May 2013 15:14:08 GMT

ブラウザはこの課題を解釈し、簡単なダイアログで資格情報の入力を求めますが、 curl を使用しているため、そうではありません。

それでは、同じリソース、つまりホームページをリクエストしましょう。ただし、それにアクセスするための資格情報も提供してください。

curl -i --user user1:user1Pass http://localhost:8080/spring-security-rest-basic-auth/api/foos/1

さて、サーバーからの応答は Cookie と共に 200 OK です。

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=301225C7AE7C74B0892887389996785D; Path=/spring-security-mvc-basic-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Wed, 29 May 2013 15:19:38 GMT

ブラウザからは、アプリケーションは正常に使用できます。唯一の違いは、すべてのブラウザが基本認証をサポートし、ユーザーに資格情報の入力を求めるダイアログを使用するため、ログインページはもはや難しい要件ではないことです。

4詳細設定 - エントリポイント

デフォルトでは、Spring Securityによってプロビジョニングされた BasicAuthenticationEntryPoint は、 401 Unauthorized 応答の全ページをクライアントに返します。エラーのこのHTML表現はブラウザではうまく表示されますが、json表現が優先される可能性があるREST APIなど、他のシナリオにはあまり適していません。

名前空間は、この新しい要件に対しても十分に柔軟です - これに対処するために - エントリポイントは上書きすることができます。

<http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>

新しいエントリポイントは標準Beanとして定義されています。

@Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

    @Override
    public void commence
      (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
      throws IOException, ServletException {
        response.addHeader("WWW-Authenticate", "Basic realm="" + getRealmName() + """);
        response.setStatus(HttpServletResponse.SC__UNAUTHORIZED);
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 - " + authEx.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("Baeldung");
        super.afterPropertiesSet();
    }
}

HTTPレスポンスに直接書き込むことで、レスポンスボディのフォーマットを完全に制御できるようになりました。

5 Mavenの依存関係

/Spring-security-with-maven[Spring Security with Mavenの記事] - 実行時に利用できる spring-security-web spring-security-config の両方が必要になります。

6. 結論

この例では、Spring SecurityとBasic Authenticationを使ってMVCアプリケーションを保護しました。 XML設定について説明し、アプリケーションを単純なcurlコマンドで処理しました。最後に、正確なエラーメッセージフォーマットを制御しました - 標準のHTMLエラーページからカスタムテキストまたはJSONフォーマットへの移行。

このチュートリアルの完全な実装はhttps://github.com/eugenp/tutorials/tree/master/spring-security-rest-basic-auth[GitHubプロジェクト]にあります - これはMavenベースのプロジェクトなので、インポートしてそのまま実行するのは簡単なはずです。

プロジェクトがローカルで実行されている場合は、サンプルHTMLにアクセスすることができます。