CORS対応 — Next.jsとSpring Bootを別ドメインで繋ぐ
はじめに
前回はNext.jsからSpring Boot APIをfetchで叩く方法を解説しました。しかしローカル開発でも実際に試すと、以下のようなエラーが出ます。
Access to fetch at 'http://localhost:8080/api/users' from origin
'http://localhost:3000' has been blocked by CORS policy.
これが CORS(Cross-Origin Resource Sharing)エラー です。今回はCORSの仕組みとSpring Boot側での設定方法を整理します。
CORSとは何か
ブラウザには「同一オリジンポリシー」というセキュリティ制限があり、異なるオリジン(ドメイン・ポート)へのリクエストをデフォルトでブロックします。
Next.js: http://localhost:3000 ←── 別オリジン ──▶ Spring Boot: http://localhost:8080
↑
ブラウザがブロック
Spring Boot側で「このオリジンからのリクエストは許可する」と宣言することで解決します。
解決方法① @CrossOriginアノテーション(手軽)
コントローラに直接つける方法です。特定のエンドポイントだけ許可したい場合に使います。
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:3000") // Next.jsのURL
public class UserController {
@GetMapping
public List<UserResponse> getUsers() {
// ...
}
}
本番URLも許可したい場合は配列で指定できます。
@CrossOrigin(origins = {
"http://localhost:3000",
"https://your-app.vercel.app"
})
解決方法② WebMvcConfigurerで全体設定(推奨)
アプリ全体のCORSをまとめて設定する方法です。コントローラが増えても設定が一箇所に集約されるため、実務ではこちらが一般的です。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**") // 対象パス
.allowedOrigins(
"http://localhost:3000",
"https://your-app.vercel.app"
)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true) // Cookie送信を許可(JWT認証で必要)
.maxAge(3600); // プリフライトのキャッシュ時間(秒)
}
}
環境変数でオリジンを管理する
URLをハードコードすると本番・開発で設定ファイルを変える必要があります。application.properties で管理しましょう。
# application.properties
cors.allowed-origins=http://localhost:3000,https://your-app.vercel.app
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Value("${cors.allowed-origins}")
private String[] allowedOrigins;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins(allowedOrigins)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
よくあるCORSエラーの原因
| エラー | 原因 |
|---|---|
blocked by CORS policy |
オリジンが許可リストにない |
| プリフライト(OPTIONS)が403 |
allowedMethodsにOPTIONSが含まれていない |
| Cookieが送られない |
allowCredentials(true) が未設定、またはfetch側に credentials: "include" がない |
Next.js側のfetchでCredentialsを送る
CookieやセッションをAPIに送りたい場合(JWT認証など)はfetch側にも設定が必要です。
const res = await fetch("http://localhost:8080/api/users", {
credentials: "include", // Cookieを送信
});
Spring Boot側で allowCredentials(true) を設定した上で、allowedOrigins に *(ワイルドカード)は使えません。必ず具体的なURLを指定してください。
まとめ
| 設定方法 | 向いているケース |
|---|---|
@CrossOrigin |
特定コントローラだけ許可したい |
WebMvcConfigurer |
アプリ全体を一括設定(実務推奨) |
| 環境変数管理 | 本番・開発でURLを切り替えたい |
次回は JWT認証(Spring Boot側) — Spring Securityでトークンを発行する設定を整理します。