yamashiro0110の日記

yamashiro0110の日記です。おもにIT技術のメモを綴っていきます(^o^)

SpringBoot入門


SpringBoot入門してみた

Spring Boot + Thymeleaf


環境

Mac OS X

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.10.4
BuildVersion:   14E46

Java

$ java -version
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)

以下のページを参考にしましたm(__)m

qiita.com qiita.com

  • Spring Data JPAでの実装について

qiita.com

  • Thymeleafの日本語ドキュメント

http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.htmlwww.thymeleaf.org

  • Spring MVCについて

d.hatena.ne.jp

個人でこれだけまとめるとかすごすぎ・・・

  • Springをより詳しく知りたいときに読む

m12i.hatenablog.com http://terasolunaorg.github.io/guideline/5.0.1.RELEASE/ja/terasolunaorg.github.io

  • 公式ドキュメント(英語)

spring.io

  • アプリケーションの設定値

http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.htmldocs.spring.io

  • 書籍


試しに、簡単なアプリケーションを作成してみた。

github.com


メモ. その1

Spring Securityで、どうやって認証が行われるのかよくわからなかった。

認証の設定は、SecurityConfigでしている。

protected void configure(HttpSecurity http)にて、アクセス認証の設定をしている。

public void configure(WebSecurity web)では、セキュリティの設定対象外として設定している。

protected void configure(HttpSecurity http)内でも、 .antMatchers("/login/form").permitAll()で同じようなことをしているが、 違いがわかっていない。。。

static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapterが、一番謎だった。

ざっくりと動作を記述する。

ログイン画面(/login/form)からFormが送信されると、 リクエストパラメータであるmailの値がLoginUserDetailService#loadUserByUsername(String username)に渡される。

この時、usernameを元にリポジトリ(DB)から対象のデータ(レコード)を取得する。 取得結果が、nullならば存在しないユーザーIDなので例外をthrowする。

存在する場合は、org.springframework.security.core.userdetails.Userを継承した、LoginUserDetailインスタンスを返す。 LoginUserDetailコンストラクタには、引数として取得したAuthUserインスタンスを設定する。

LoginUserDetailコンストラクタ内では、org.springframework.security.core.userdetails.Userコンストラクタを呼び出している。 呼び出しているコンストラクタの引数は、User(String username, String password, Collection<? extends GrantedAuthority> authorities)となっている。 1, 2番目の引数は見ての通り、username, passwordになっている。

この値が、Formで送信された値と比較される。 パスワードは、SecurityConfig.AuthenticationConfiguration#init(AuthenticationManagerBuilder auth)内で 設定したpasswordEncoder(getPasswordEncoder())によって暗号化されて比較されるぽい。

Collection<? extends GrantedAuthority> authoritiesについては、 よくわかってないが認証したユーザーの権限を渡しているみたい。

わかったら追記。。。

LoginUserDetailについて

  • LoginUserDetailは、org.springframework.security.core.userdetails.Userを継承したクラス
  • org.springframework.security.core.userdetails.Userは、org.springframework.security.core.userdetails.UserDetailsの実装なので、拡張(継承)して使う
  • org.springframework.security.core.userdetails.UserDetailsは、認証ユーザーの情報を取得するためのAPIを定義したinterface

メモ. その2

CSRFについて。

Spring Securityを有効にすると、デフォルトでCSRF対策が有効になるが、 Thymeleaf側で、正しくform要素を定義しないといけない。

以下のように、<form> ~ </form>th:action属性を追加することで、 自動的に<input type="hidden" name="_csrf" value="e5521ea3-3cc5-4be4-84a5-7acd9ce10987" />のような トークンがリクエストパラメータとして追加される。

<form th:action="@{/xxx/xxx}" method="xxx">
    ~
</form>

正しく設定されてない場合は、403でエラーとなる。


メモ. その3

Thymeleafでの、バリデーションエラーの表示について。

見たほうがわかりやすい。

<form th:object="${user}" th:action="@{/user/input}" method="POST">
    ~ 省略 ~
    <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">error</p>
    ~ 省略 ~
</form>

上記について。

  • th:if="${#fields.hasErrors('name')}"

    • userオブジェクトのnameフィールドにエラーが存在するか
  • th:errors="*{name}"

    • nameフィールドのエラーを表示する

Thymeleafがオブジェクトのプロパティにアクセスする場合は、 getXxxisXxxxメソッドに対して、xxxという名前に変換してアクセスするので、 アクセスするプロパティにはGetterが必要。

ex) user.name <- user.getName()

なので、Getterメソッドだけ定義してフィールドを宣言しなくてもOK。

ex) sample.user.auth.domain.AuthUser#isCheckPassword

この辺の実装は↓

  • sample.user.controller.UserController#confirm
  • src/main/resources/templates/user/form.html

SpringBootを使ってみて

Springの面倒な設定がいらない。

Springのみの場合、xmlとかannotationでいろいろ設定しないといけない

最初、理解するためにSpringだけでやってみようとしたけど、設定で躓いて諦めた。。。

ライブラリを追加する場合でも、SpringBootがよしなにやってくれるのでかなり楽。

組み込みのWebサーバがある。

ビルドしたらjarが作られるので、配置先のサーバでjava -jar xxx.jarでAPサーバが立ち上がる(!) Gradleだと、gradle bootRunで一発(!)

Annotationつけるだけで、全部設定してくれる。

ある程度わかってくると楽になっていいけど、初めはつらいかも。。