今日もまたサンプルを見ながら、できそうなものを調べていこうと思う。
STSとは?
STSは、Spring Tool Suiteの略で、EclipseベースのIDEの模様。
とりあえず自分には必要なさそうと判断したので放置しよう…。
一応、DL先のURLはこちら。http://spring.io/tools/sts/all
Securing a Web Applicationをやってみる
順序立てて何をやればいいのかがわからなかったので、ざっと眺めてやっておくべきことであろう、セキュアなWebアプリっていう項目に目をつけた。
まずはhtmlを追加。ThymeleafでURLのリンクを書く場合は、th:href=”@{/hello}”などと書くようだ。
01 02 03 04 05 06 07 08 09 10 11 12 | <! DOCTYPE html> < head > < title >Spring Security Example</ title > </ head > < body > < h1 >Welcome!</ h1 > < p >Click < a th:href = "@{/hello}" >here</ a > to see a greeting.</ p > </ body > </ html > |
次に、リンク先のhtmlを記述する。
01 02 03 04 05 06 07 08 09 10 11 | <! DOCTYPE html> < head > < title >Hello World!</ title > </ head > < body > < h1 >Hello world!</ h1 > </ body > </ html > |
そして、WevMvcConfigurerAdapterを継承したMvcConfigクラスを作る。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | package sample; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController( "/home" ).setViewName( "home" ); registry.addViewController( "/" ).setViewName( "home" ); registry.addViewController( "/hello" ).setViewName( "hello" ); registry.addViewController( "/login" ).setViewName( "login" ); } } |
addViewControllerを呼び出して、コントローラーをセットし、setViewNameでテンプレートもセットする。これでURLとテンプレートがマッピングされた形か。ちなみにまだlogin.htmlは作っていないが、gradle bootRunは動いた。
http://localhost:8080/homeにアクセスしたら、ちゃんと表示された。リンクも貼られていて、http://localhost:8080/helloに遷移することができた。
Spring Securityをセットアップする
ここからが本題だろう。
このままだと/helloに普通にアクセスできてしまうので、Basic認証をつけよう!ってことらしい。そのためには、build.gradleのdependenciesブロックに以下を追加する。
1 2 3 4 5 6 7 8 | dependencies { // compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE") // compile("org.springframework.boot:spring-boot-starter-actuator:1.2.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.2.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-security:1.2.1.RELEASE") compile("org.webjars:jquery:2.1.3") testCompile("org.springframework.boot:spring-boot-starter-test:1.2.1.RELEASE") } |
その後、WebSecurityConfigクラスを作成。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package sample; import org.springframework.beans.factory.annotation.Autowired; 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.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; @Configuration @EnableWebMvcSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( "/" , "/home" ).permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage( "/login" ) .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser( "user" ).password( "password" ).roles( "USER" ); } } |
@EnableWebMvcSecurityアノテーションを使うことで、Springのセキュリティサポートを利用することができるようになる模様。
configureメソッドをオーバーライドして、URLのアクセス制限を設定していくようだ。ここでは、/と/homeは全部許可しているけれど、それ以外は認証が必要にしてあるように見える。
formLogin以降で、ログインページのURLを設定し、このページは誰でも見られるように設定されている。
configureGlobalメソッドで、ログイン用の情報が設定してあるようだが、てっきりBasic認証だと思っていたら、違った。
とりあえずこのままだとログインページがないので作成する。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | <! DOCTYPE html> < head > < title >Spring Security Example </ title > </ head > < body > < div th:if = "${param.error}" > Invalid username and password. </ div > < div th:if = "${param.logout}" > You have been logged out. </ div > < form th:action = "@{/login}" method = "post" > < div >< label > User Name : < input type = "text" name = "username" /> </ label ></ div > < div >< label > Password: < input type = "password" name = "password" /> </ label ></ div > < div >< input type = "submit" value = "Sign In" /></ div > </ form > </ body > </ html > |
特に設定しない場合だと、input name=”username”とinput name=”password”を/loginに対してPOSTすれば認証が行われるようだ。楽といえば楽。だが、このままだとサインアウトできないので、hello.htmlを修正してみようってことだったので、やってみる。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | <! DOCTYPE html> < head > < title >Hello World!</ title > </ head > < body > < h1 th:inline = "text" >Hello [[${#httpServletRequest.remoteUser}]]!</ h1 > < form th:action = "@{/logout}" method = "post" > < input type = "submit" value = "Sign Out" /> </ form > </ body > </ html > |
これを見る限りだと、/logoutに対してPOSTでアクセスしたらログアウトのようだ。
Sign Outボタンをクリックしたらちゃんとログアウトできた。Basic認証はわからなかったものの、アクセス制限の方法はだいたいわかった。この認証部分をDBのデータに関連付けたりすれば、一般的なユーザーログイン画面みたいなものが作れるのだろうか?セッション周りのこととかもまだわからないので、調べていきたい。
また今回作ったクラスは自動的に利用されていたようなので、gradleのspring-boot pluginのおかげなんだろう。