Spring Boot で実装している Web API に、Spring Security を使って認証を追加することにした。 最終的には OAuth にする予定だけど、今はまだ検証用のプロトタイプを作っている段階なので、とりあえず Basic 認証で。
まず build.gradle を修正して、Spring Security を追加する。
buildscript { ext { springBootVersion = '1.5.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') // Spring Security を追加 compile('org.springframework.boot:spring-boot-starter-security') }
Basic 認証を組み込んだ、最小の Spring Boot アプリケーションがこちら。
package jp.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class BasicAuthExampleApplication { public static void main(String[] args) { SpringApplication.run(BasicAuthExampleApplication.class, args); } @RestController public static class HomeController { @GetMapping("/api/goodmorning") public String goodMorning() { return "Good morning"; } @GetMapping("/api/hello") public String hello() { return "Hello world"; } } @Configuration @EnableWebSecurity public static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder.inMemoryAuthentication() .withUser("test_user").password("test_pass").roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic() // Basic 認証を有効にする .and() .authorizeRequests() .antMatchers("/api/goodmorning") // /api/goodmorning は認証不要 .permitAll() .anyRequest() .authenticated(); // それ以外は認証必須 } } }
Python の REPL で動作確認。
>>> import requests >>> requests.get("http://localhost:8080/api/goodmorning").text u'Good morning' >>> requests.get("http://localhost:8080/api/hello").text u'{"timestamp":1498106201915,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/api/hello"}' >>> requests.get("http://localhost:8080/api/hello", auth=("test_user", "test_pass")).text u'Hello world'