【Java】Spring SecurityにCORS設定を追加する
Spring SecurityにCORS設定を追加
以下の記事で作成したSpring Securityを使用しWeb APIのリクエストごとにトークンで認証する処理にCORS設定を追加します。
下記のコードの中でCORS設定に関連するのはコメントを入れた箇所です。
まず、configureメソッド内でcorsメソッドの呼び出しを追加します。このメソッドは引数無しで呼び出すと「corsConfigurationSource」という名前のBean定義からCORS設定を読み込みます。
次に、「corsConfigurationSource」という名前でCorsConfigurationSourceクラスのインスタンスのBean定義を作成します。CorsConfigurationクラスのインスタンスを作成し、CORSに関連するヘッダの値を設定します。
UrlBasedCorsConfigurationSourceクラスのインスタンスのregisterCorsConfigurationメソッドの第一引数にCOSR設定を行うパス、第二引数に作成したCORS設定指定します。
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity()
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.addFilter(preAuthenticatedProcessingFilter())
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.cors(); // CORS設定をcorsConfigurationSource()から読み込む
}
@Bean
public AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> authenticationUserDetailsService() {
return new MyAuthenticationUserDetailService();
}
@Bean
public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() {
var preAuthenticatedAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
preAuthenticatedAuthenticationProvider.setPreAuthenticatedUserDetailsService(authenticationUserDetailsService());
preAuthenticatedAuthenticationProvider.setUserDetailsChecker(new AccountStatusUserDetailsChecker());
return preAuthenticatedAuthenticationProvider;
}
@Bean
public AbstractPreAuthenticatedProcessingFilter preAuthenticatedProcessingFilter() throws Exception {
var preAuthenticatedProcessingFilter = new MyPreAuthenticatedProcessingFilter();
preAuthenticatedProcessingFilter.setAuthenticationManager(authenticationManager());
return preAuthenticatedProcessingFilter;
}
// CORS設定を行うBean定義
@Bean
public CorsConfigurationSource corsConfigurationSource() {
var configuration = new CorsConfiguration();
// Access-Control-Allow-Origin
configuration.setAllowedOrigins(List.of("*"));
// Access-Control-Allow-Methods
configuration.setAllowedMethods(List.of("*"));
// Access-Control-Allow-Headers
configuration.setAllowedHeaders(List.of("*"));
// Access-Control-Allow-Credentials
configuration.setAllowCredentials(true);
var source = new UrlBasedCorsConfigurationSource();
// COSR設定を行う範囲のパスを指定する。この例では全てのパスに対して設定が有効になる
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
参考サイト
動作検証
動作検証のためにボタンをクリックするとGETリクエストを投げるだけのHTMLファイルを作成しました。このファイルをhttp-serverでlocalhost上に立てたサーバに配置実しブラウザからアクセスします。
この記事の例ではhttp-serverは8080ポートで起動しています。
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
async function sendGetRequest() {
try {
const config = {
headers : {
Authorization: "key1"
}
};
const params = {};
const data = await axios.get("http://localhost:8080/items/1", config);
console.log(data);
} catch (e) {
console.log(e);
}
}
</script>
</head>
<body>
<button onclick="sendGetRequest()">Send GET Request</button>
</body>
</html>
CORSアクセスが成功する場合
上記のJavaコードでconfiguration.setAllowedOrigins(List.of(“*"));とした場合はAPIへのリクエストが成功しレスポンスを受け取ることができます。
今回API側はAuthorizationヘッダの値により認証を行っています。リクエストヘッダにAuthorizationヘッダをつけるため、プリフライトリクエストが送信されます。 プリフライトリクエストはGETなどの実際のリクエストを送信する前にOPTIONSメソッドによるリクエストを送信しリクエストの安全性を確かめます。
プリフライトリクエストの詳細はオリジン間リソース共有 (CORS)プリフライトリクエストを参照してください。
CORSアクセスが失敗する場合
上記のJavaコードでconfiguration.setAllowedOrigins(List.of(“http://localhost:9000"));とした場合はAPI側でアクセスを許可したオリジンとリクエスト元が異なるためAPIへのリクエストが失敗します。
プリフライトリクエストが403エラーとなります。
プリフライトリクエストがエラーとなるため、GETリクエストは送信されません。