APIごとのアクセス制御とスコープ管理をやさしく解説!Spring Security初心者ガイド
新人
「Spring Securityって聞いたことあるんですが、APIのアクセス制御ってどうやるんですか?」
先輩
「Spring Securityは、APIのセキュリティやアクセス権限を細かく制御できるフレームワークなんだよ。」
新人
「APIごとにアクセス制御ってどういう意味ですか?必要なんですか?」
先輩
「いい質問だね。APIごとに許可されたユーザーやロールを分けることで、セキュリティを保てるんだ。詳しく説明するよ!」
1. Spring Securityとは?アクセス制御の基本を理解しよう
Spring Security(スプリング・セキュリティ)は、Spring Frameworkに統合できるセキュリティ機能を提供する仕組みです。APIやWebアプリケーションに対して、「誰が・どのリソースに・どんな操作をして良いか」を細かく設定できます。
アクセス制御の仕組みは、例えば次のように動作します。
- ログインしていないユーザーは、管理者画面にアクセスできない
- 一般ユーザーは、商品情報を「見る」ことはできるが、「削除」はできない
- 管理者だけがユーザー一覧APIを叩けるようにする
こういった認可(Authorization)の仕組みを、Spring Securityが担ってくれます。初心者でも安心して使えるように、標準設定でもある程度のセキュリティが保たれるのも特長です。
2. なぜAPIごとにアクセス制御が必要なのか?
APIは、クライアントアプリケーションや外部システムとデータをやり取りする重要な窓口です。適切にアクセス制御をしないと、以下のようなリスクが生じます。
- 未認証のユーザーが機密データにアクセスできてしまう
- 一般ユーザーが管理者専用機能を実行してしまう
- 悪意のあるリクエストでデータが削除されたり、書き換えられたりする
このような事態を防ぐためには、APIごとにアクセス可能なユーザーやロールを明確に区別し、それに応じたスコープ(範囲)を設定する必要があります。
アクセス制御は、アプリケーションのセキュリティを守る第一防衛線とも言えます。Spring Securityを使えば、これらの制御を簡単に行うことができます。
3. URLやメソッドごとのアクセス制御の考え方
Spring Securityでは、特定のURLやHTTPメソッドに対して、アクセス制御を設定することができます。以下のような指定が可能です。
/admin/**へのアクセスはROLE_ADMINのユーザーのみ/api/productsのGETは誰でもOK、POSTは認証ユーザーのみ/api/users/deleteはROLE_MANAGER以上のみ許可
こうした制御は、Javaコードで柔軟に記述できます。以下は、アクセス制御の設定例です。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/products").authenticated()
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
このように、URLパターンやHTTPメソッドに応じて、細かく制御ができます。初心者でも一つずつ設定していけば、安全で信頼性の高いAPIを構築できます。
実際のプロジェクトでは、管理者・一般ユーザー・ゲストなどのロール(役割)に応じてアクセス範囲を変えることが多いため、スコープを明確に分けて設計しておくことがポイントです。
4. Spring Securityでのアクセス制御を@Controllerで実装してみよう
ここでは、@Controllerを使ったSpring MVCの基本的な構成で、アクセス制御を実装する方法を紹介します。初心者にとっては、REST APIではなくHTML画面を返すコントローラーの構成のほうが理解しやすいでしょう。
以下の例では、ログインユーザーだけがアクセスできる画面と、管理者のみアクセスできるページを分けて構成しています。
@Controller
public class PageController {
@GetMapping("/home")
public String homePage() {
return "home";
}
@GetMapping("/admin/dashboard")
public String adminPage() {
return "admin-dashboard";
}
}
homeは誰でもアクセスできるようにして、admin/dashboardはROLE_ADMIN(管理者権限)だけが見られるように設定します。こうすることで、ページごとにアクセス制限をかけることが可能になります。
Spring Securityの設定と組み合わせることで、これらのルールを反映できます。
5. authorizeHttpRequests()でアクセス制限を細かく設定する
http.authorizeHttpRequests()メソッドは、リクエストごとのアクセス制御を記述する中心的な機能です。初心者でも扱いやすく、柔軟にルールを記述できます。
たとえば、次のように設定することで、ページごとに異なるアクセス制御を設定できます。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/home").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
ここで使われているrequestMatchers()は、特定のパス(URL)にアクセス制限をかけるためのメソッドです。
permitAll():全ユーザーに許可hasRole("ADMIN"):ADMINロールを持つユーザーのみ許可authenticated():ログイン済みであれば許可
このように記述することで、ログインしていないユーザーは管理者画面を見られないようになります。
初心者の方は、まずpermitAll()とauthenticated()から試すと理解しやすいでしょう。
6. ロール(ROLE_USERなど)を使ったアクセス制御の仕組みと実例
Spring Securityでは、ユーザーの役割をロール(Role)として定義し、それに応じてアクセス制限を設定します。
たとえば、「ROLE_USER」や「ROLE_ADMIN」などのロールを設定することで、一般ユーザーと管理者でアクセスできる範囲を分けることができます。
以下は、ユーザーにロールを割り当てたうえでアクセス制御を行う例です。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withUsername("user")
.password("{noop}userpass")
.roles("USER")
.build();
UserDetails admin = User.withUsername("admin")
.password("{noop}adminpass")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/user/**").hasRole("USER")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
userにはROLE_USER、adminにはROLE_ADMINが割り当てられており、それぞれ対応するパスにだけアクセスできます。
初心者の方は最初、「ロール名には自動的にROLE_が付く」ことに注意してください。.roles("ADMIN")と書くと、内部的にはROLE_ADMINとして扱われます。
このような設計をしておくことで、実際の業務システムでも以下のような制御が可能になります。
- 商品ページは全員閲覧可能
- 購入履歴はログインユーザーのみ
- ユーザー管理機能は管理者のみ
ロールベースのアクセス制御は、初心者でもわかりやすく、現実の業務システムにも応用しやすいため、しっかり学んでおくことをおすすめします。
7. スコープ管理とは?役割や目的を初心者向けに解説
スコープ管理(Scope Management)とは、アクセス可能な機能やリソースの「範囲」を明確に定めることを意味します。Spring Securityにおいても、このスコープ管理は非常に重要な考え方です。
たとえば、「このユーザーは商品情報を見るだけはできるが、編集や削除はできない」といった制限をかけたい場合、これがまさにスコープの考え方です。
図で表すと、以下のようになります。
[全ユーザー]→ 商品一覧の閲覧のみ可
[認証ユーザー]→ 商品購入・注文履歴確認など
[管理者]→ 商品の追加・編集・削除が可能
このように、ユーザーの種類や目的に応じて、APIの利用可能範囲(スコープ)を制御するのがスコープ管理の基本です。
8. アクセススコープと認可(Authorization)の関係性
スコープは、Spring Securityで実現する認可(Authorization)の中核に関わります。認可とは、ユーザーがそのリクエストを実行して良いかを判断する仕組みです。
認可は通常、以下のような情報をもとに行われます。
- ログイン状態(認証済みか)
- ユーザーのロール(例:ROLE_USER, ROLE_ADMIN)
- ユーザーのスコープ(例:read_only, write, manage)
つまり、スコープとは「どこまで許可するか」を示す指標であり、認可のための条件の一部として機能します。
Spring Securityでは、通常のロールによる制御に加えて、OAuth2連携などでスコープを活用する場合もありますが、この記事では@Controllerを使ったシンプルなアクセス制御を中心に説明しています。
たとえば、あるユーザーが「データの参照はできるが更新はできない」というスコープを持っている場合、それをプログラム上で判断して処理を分けることが可能です。
9. APIごとに異なるスコープを設定する実践例
ここでは、APIを複数のスコープに分けて制御する具体的な例を紹介します。まずは、読み取り専用(Read Only)と、管理者用(Admin Only)に分けたパターンです。
次のように@Controllerでページを用意し、それに対するアクセス制限をSpring Securityで定義します。
@Controller
public class ProductController {
@GetMapping("/products/view")
public String viewProducts() {
return "product-list";
}
@PostMapping("/products/add")
public String addProduct() {
return "product-add";
}
@PostMapping("/products/delete")
public String deleteProduct() {
return "product-delete";
}
}
このコードでは、/products/viewは誰でも閲覧可能、/products/addと/products/deleteは管理者専用にしたいという設計です。
そのためのSpring Security側の設定は次のようになります。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/products/view").permitAll()
.requestMatchers("/products/add", "/products/delete").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
このように、APIのパスごとにアクセススコープ(ここでは読み取り専用と管理者限定)を明確に分けて設定することが可能です。
さらに、OAuth2を使った外部認証と組み合わせると、以下のような高度なスコープ制御も実現できます(今回は割愛しますが、将来的に学ぶと役立ちます)。
例:
- scope: read → GETリクエストのみ許可
- scope: write → POST, PUT, DELETEを許可
- scope: admin → 管理機能へのアクセス許可
このように、Spring Securityでは、スコープとロールをうまく使い分けることで、安全で柔軟なアクセス制御が実現できます。
初心者のうちはまず、ロール単位でのアクセス制御に慣れ、次にスコープの考え方を取り入れていくと、自然にセキュアなシステムが構築できるようになります。