Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その57 )( 気になった点を修正2 )
概要
Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その56 )( TableDataAssert クラスの機能追加 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- WebSecurityConfig の DEFAULT_SUCCESS_URL の値を変更する。
- 画面上部のメニューはログインしたユーザの権限で使用可能なもののみ表示する。
- セッション用の Cookie 名が JSESSIONID ではなく SESSION になっているので WebSecurityConfig を修正する。
* (2016/03/19追記)セッション用の Cookie 名が JSESSIONID ではなく SESSION になっているのは Spring Session あたりを入れているからではないかと思われます。別に作成している Spring Boot の Web アプリケーションを見てみたら JSESSIONID でした。要注意です。
参照したサイト・書籍
- thymeleaf/thymeleaf-extras-springsecurity
https://github.com/thymeleaf/thymeleaf-extras-springsecurity
目次
- WebSecurityConfig の DEFAULT_SUCCESS_URL の値を変更する
- 画面上部のメニューはログインしたユーザの権限で使用可能なもののみ表示する
- セッション用の Cookie 名が JSESSIONID ではなく SESSION になっているので WebSecurityConfig を修正する
手順
WebSecurityConfig の DEFAULT_SUCCESS_URL の値を変更する
デフォルトの URL は貸出希望書籍 CSV ファイルアップロード画面 ( /booklist ) に変更します。
feature/104-issue ブランチを作成します。
src/main/java/ksbysample/webapp/lending/config の下の WebSecurityConfig.java を リンク先のその1の内容 に変更します。
src/test/java/ksbysample/webapp/lending/web の下の LoginControllerTest.java を リンク先の内容 に変更します。
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
ブラウザを起動し http://localhost:8080/ へアクセスします。ログイン画面が表示されますので、USER_ADMIN 権限を持たないユーザでログインします。ID に "suzuki.hanako@test.co.jp"、Password に "hanako" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。
ログイン後、貸出希望書籍 CSV ファイルアップロード画面が表示されます。
Ctrl+F2 を押して Tomcat を停止します。
Gradle projects View から clean タスクの実行→「Rebuild Project」メニューの実行→build タスクの実行を行い、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。
Project View のルートでコンテキストメニューを表示して「Run 'All Tests' with Coverage」を選択し、テストが全て成功することを確認します。
commit、GitHub へ Push、feature/104-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/104-issue ブランチを削除、をします。
画面上部のメニューはログインしたユーザの権限で使用可能なもののみ表示する
以下の仕様に変更します。
- メニューは「貸出希望書籍登録」「検索対象図書館登録」の2つだけにする。
- 「検索対象図書館登録」は ROLE_ADMIN 権限を持つユーザだけ表示する。
実装します。
feature/107-issue ブランチを作成します。
src/main/resources/templates/common の下の mainparts.html を リンク先の内容 に変更します。
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
http://localhost:8080/ にアクセスします。ログイン画面が表示されたら ID に "tanaka.taro@sample.com"、Password に "taro" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。
ROLE_ADMIN 権限を持つユーザなので検索対象図書館登録画面が表示されます。メニューにも「検索対象図書館登録」が表示されることが確認できます。
ログイン画面に戻り、今度は ID に "suzuki.hanako@test.co.jp"、Password に "hanako" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。
ROLE_ADMIN 権限を持たないユーザなので貸出希望書籍 CSV ファイルアップロード画面が表示されます。メニューには「検索対象図書館登録」が表示されないことが確認できます。
Ctrl+F2 を押して Tomcat を停止します。
commit、GitHub へ Push、feature/107-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/107-issue ブランチを削除、をします。
セッション用の Cookie 名が JSESSIONID ではなく SESSION になっているので WebSecurityConfig を修正する
Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( 番外編 )( AspectJ でログを出力する ) で Cookie の値を出力した時に [req][cookie] name = SESSION, value = b264c91f-4b0d-4a2f-8462-b4bdd4b58de2, domain = null, path = null, maxage = -1, secure = false, httponly = false
と出力されたのですが、セッション用の Cookie 名が JSESSIONID ではなく SESSION になっていました。
Chrome でも確認しましたが、やっぱり SESSION ですね。いつの間に変わったのでしょうか???
WebSecurityConfig クラスに、ログアウト時に削除する Cookie として JSESSIONID と書いている部分があるので修正します。
feature/117-issue ブランチを作成します。
src/main/java/ksbysample/webapp/lending/config の下の WebSecurityConfig.java を リンク先のその2の内容 に変更します。
Tomcat を起動してログイン、ログアウトが動作することを確認します。(たいした修正ではないので詳細は記述しません)
commit、GitHub へ Push、feature/117-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/117-issue ブランチを削除、をします。
ソースコード
WebSecurityConfig.java
■その1
@Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public static final String DEFAULT_SUCCESS_URL = "/booklist"; public static final String REMEMBERME_KEY = "ksbysample-webapp-lending";
- DEFAULT_SUCCESS_URL の値を
/loginsuccess
→/booklist
に変更します。
■その2
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/html/**").permitAll() .antMatchers("/encode").permitAll() .antMatchers("/urllogin").permitAll() .antMatchers("/webapi/**").permitAll() .antMatchers("/springMvcMemo/**").permitAll() .antMatchers("/textareamemo/**").permitAll() .anyRequest().authenticated(); http.formLogin() .loginPage("/") .loginProcessingUrl("/login") .defaultSuccessUrl(WebSecurityConfig.DEFAULT_SUCCESS_URL) .failureUrl("/") .usernameParameter("id") .passwordParameter("password") .successHandler(new RoleAwareAuthenticationSuccessHandler()) .permitAll() .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/") .deleteCookies("JSESSIONID") .deleteCookies("remember-me") .invalidateHttpSession(true) .permitAll() .and() .rememberMe() .key(REMEMBERME_KEY) .tokenValiditySeconds(60 * 60 * 24 * 30); }
.deleteCookies("JSESSIONID")
→.deleteCookies("SESSION")
へ変更します。
LoginControllerTest.java
@Test public void 存在するメールアドレスを指定すればログインに成功する() throws Exception { // ログイン前にはログイン後の画面にアクセスできない mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL)) .andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/")) .andExpect(unauthenticated()); // 存在するメールアドレスを指定して /urllogin にアクセスすればログインできる MvcResult result = mvc.noauth.perform(get("/urllogin?user=" + mvc.MAILADDR_SUZUKI_HANAKO)) .andExpect(status().isFound()) .andExpect(redirectedUrl(WebSecurityConfig.DEFAULT_SUCCESS_URL)) .andExpect(authenticated().withUsername(mvc.MAILADDR_SUZUKI_HANAKO)) .andReturn(); HttpSession session = result.getRequest().getSession(); assertThat(session).isNotNull(); // ログイン後の画面にアクセスしてもエラーにならない mvc.noauth.perform(get(WebSecurityConfig.DEFAULT_SUCCESS_URL).session((MockHttpSession) session)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("booklist/booklist")) .andExpect(model().hasNoErrors()) .andExpect(authenticated().withUsername(mvc.MAILADDR_SUZUKI_HANAKO)); }
mvc.MAILADDR_TANAKA_TARO
→mvc.MAILADDR_SUZUKI_HANAKO
に変更します。.andExpect(view().name("loginsuccess"))
→.andExpect(view().name("booklist/booklist"))
に変更します。
mainparts.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> .......... <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse pull-left" id="navbar-collapse"> <ul class="nav navbar-nav"> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">メニュー <span class="caret"></span></a> <ul class="dropdown-menu" role="menu"> <li><a href="/booklist">貸出希望書籍登録</a></li> <li class="divider" sec:authorize="hasRole('ROLE_ADMIN')"></li> <li sec:authorize="hasRole('ROLE_ADMIN')"><a href="/admin/library">検索対象図書館登録</a></li> </ul> </li> </ul> </div> <!-- /.navbar-collapse -->
- html タグに
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
を追加します。この設定は sec:authorize 等の thymeleaf-extras-springsecurity3 の機能を仕様する html ファイル内にのみ記述すればよく、th:replace で呼び出す側には記述する必要はありません。 - 以下の4行を削除します。
<li><a href="/lendingapp">貸出申請</a></li>
<li><a href="/confirmresult">貸出申請結果確認</a></li>
<li class="divider"></li>
<li><a href="/lendingapproval">貸出承認</a></li>
- 「検索対象図書館登録」メニューとその上の区切り線の li タグに
sec:authorize="hasRole('ROLE_ADMIN')"
を追加します。
履歴
2016/03/17
初版発行。
2016/03/19
* 概要に、セッション用の Cookie 名が SESSION になっていることに関するコメントを追記しました。