Furyu
[フリュー公式]

Tech Blog

フリュー株式会社の技術ブログです

2017年07月24日

SatoKeita

Spring Securityを使ったAjax通信について

こんにちは。フリューのジョンです。

最近はVue.jsがあればテンプレートエンジンなんていらないと思いながらThymeleafを触っています。

さて、今回はSpring Securityを使ったAjax通信についてハマったのでそれの解消方法について書かせていただきます。

具体的には、Spring Securityの機能の一つである、クロスサイトスクリプティング防止機能でハマりました。

クロスサイトスクリプティングの説明については、今回省きます。他サイトを参照してください。

概要

環境は以下のとおりです。

spring-boot 1.5.3.RELEASE
spring-boot-starter-security 1.5.3.RELEASE
Thymeleaf 3.0.6.RELEASE

結論から言えば、Spring Securityを導入すると、単純なPOSTアクセスをすることができなくなります。
理由としては、認可した場所からのリクエストであることを検証するためにトークンが必要になるためです。その為、これを解消するには以下の方法があります。

  • Formにトークンを付ける。
  • Cookieにトークンをつけて、リクエストヘッダにトークンをつけて送信する。
  • GETで対処する  ← ダメゼッタイ、ユルサナイ

上手くいかない例

まずうまくいかない、例を見てみましょう。

この状態でボタンを叩くと以下のような画面になります。

spring-security-postが上手くいかない例

Formにトークンを付ける

これはSpring Security+Thymeleafを導入すると簡単に対応できます。

具体的にはFormのaction属性をThymeleafのものにします。

Formタグを見てみると自動でinput[type=’hidden’]が追加されているのがわかると思います。

spring-security-form送信(上手くいく例

Ajaxにする場合、このinput[name=’_csrf’]の値をJavaScriptで取得すれば良いのです。しかし、この方法はFormタグがなければ成り立ちません。

FormがないAjaxのpost通信をするためには、以下の方法があります。

Cookieにトークンをつけて、リクエストヘッダにトークンをつけて送信する

Spring Securityでは、Cookieにトークンをつけることができます。そのためには、CookieCsrfTokenRepositoryを使用します。

withHttpOnlyFalseとしているのは、HTTPでもCookieにトークンをつけてもらうためです(デフォルトはHTTPSだけにしかCookieは付いてきません)。リクエストを見てみると、以下のようにXSRF-TOKENという名前のCookieがついているのがわかります。

spring-security-cookieが付いている

このCookieの値をJavaScriptで読み込み、リクエストヘッダにX-XSRF-TOKENをつけます。

これによりAjax通信が可能になります。しかし、いちいちCookieをとってリクエストヘッダに渡すのは面倒ですね。

Axiosというライブラリではそれを解消してくれます。内部でcookie()を見て、リクエストヘッダに追加してくれているのです。

非常に便利ですね。

Cookieの名前、ヘッダの名前は、デフォルトの値ですので、変更可能です。もちろんAxiosの方も変更が可能です。

AxiosのFormData通信

ちょっと話が変わりますが、Spring SecurityでのAjaxのlogin機能を実装しようとした時、すこし、ハマりましたので追記します。

Axiosで通信するとデフォルトはJsonでの通信になります。しかし、loginには、FormDataでパラメータを渡さなければいけません。

実装方法としては、以下のようにAxiosのpostメソッドの第3パラメータに変換メソッドを追加してあげます。

まとめ

Spring Securityを使ったajax通信は少しだけ工夫が必要です。
しかし、その設定は本当に少しだけです。
ここではSpring Securityの機能自体について触れませんでしたが、Spring Securityは本当に素晴らしいので、ぜひ使ってみてください。

そして、Ajax通信だけのために、jQueryを使うのは止めましょう。Axiosを使ってみましょう。(個人の感想です)

最後に

弊社は、Springを実践利用してバリバリコード書きたいエンジニア募集中です!

詳しくはこちら


2017年07月24日

SatoKeita

Doma2を使った複数データベースアクセス

こんにちは。フリューのジョンです。

個人的意見ではありますがSpring Data JPAのほうが好きですが、今回はDoma2を使った複数データベースアクセスを実装して躓いたので書かせていただきたいと思います。

概要

環境としましては以下のようになります。

spring-boot 1.5.3.RELEASE
doma-spring-boot-starter 1.1.0
spring-boot-starter-aop 1.5.4.RELEASE

複数のデータベースアクセスの具体的な要件は以下になります。

  • データベースアクセスをするメソッドに対して、アノテーションを付けてアクセス先を切り替える
  • アノテーションを付けていない場合はデフォルトのデータベースにアクセスする
  • 接続先はDomaの基本に合わせて、DataSourceの切り替えをしたい

以上の要件を満たすために、AbstractRoutingDataSourceとAnnotation、ThreadLocalを利用しました。

実装については、Qiitaの「Spring Bootで複数データベースを扱うウェブアプリケーションのサンプル」の記事を参考にさせていただきました。

実装

Daoには実装は加えません。

肝になるのは、AbstractRoutingDataSourceです。AbstractRoutingDataSourceはSpringのJDBCパッケージの中にあります。
このクラスを実装したモノを、Domaのconfigを継承したConfigrationクラスが返却することで対応が可能です。

ここで、AppConfigはルートである必要があります。(もしかすると、そうでなくてもいける方法があるのかもしれませんが、私が調べた限り出来ませんでした……)

接続先を保存するためにstaticでデータを作っておきます。ThreadLocalですので取扱には注意です。

メソッドに必要なアノテーションは以下のように設定します

アノテーションの実装は以下になります。
アノテーションがあるメソッドが動く前に接続先をHolderにセットして、動作した後に開放しています。

接続先はenumで持つようにします。

ここまでで実装終わりです。

使い方

以下のようになります。

まとめ

今回はアノテーションを使った振り分け方を行いましたが、リクエストパラメータやCookieを使って振り分けるというのも良いかと思います。

Doma2がConfigを勝手に参照してくれるのは、とても楽ですね。設定だけでうまくいきました。

最後に

弊社は、Springを実践利用してバリバリコード書きたいエンジニア募集中です!

詳しくはこちら


2017年06月7日

SatoKeita

Vue.jsを使ってみよう その3

こんばんは、フリューのジョンです。Vue.jsを社内に広める活動を頑張ってます。

前回はVue.jsの基本の話、elプロパティ、dataプロパティ、methodsプロパティの話をしました。
今回はVue.jsのHTML側(v-bind、v-model、v-on)の話をしていきたいと思います。

今回もVue.jsはバージョン2.3.0を使用します。

v-bindやv-onなどの属性を、Vue.jsでは、それぞれを「ディレクティブ」と呼んでいます。

v-bindディレクティブ

タグ要素のattributeにdataプロパティやmethodsプロパティの結果を当てはめる(バインドする)事ができます。

classやstyleの属性については、少し特殊な書き方で値をバインドすることができます。

v-modelディレクティブ

v-bindでは属性値に値を入れることができましたが、v-bindでは入れるだけではなく、監視して更新することができます。
更新が走る属性値、つまり、inputやtextareaタグのvalue属性につけることでその値を監視することができます。

selectに対しても記述することができます。この際、初期値のvalueがselectedになることを覚えておきましょう。

v-onディレクティブ

属性に、eventに対する振る舞いを指定することができます

記述した関数に引数を渡すことも可能です。

click以外にもkeyupなども使うことができます。ただし、v-modelとの競合に気をつけてください。

補足

ここまでのディレクティブを使用することで、画像を一定時間ごとに切り替えるスライドショーを作ることができます。
また、v-modelとv-onを使い、画像を動的に追加するなどと行った処理を追加するなどができます。

まとめ

v-bind、v-on、v-modelで、データバインディングについて、大まかな説明が終わりました。

これにより、簡単なアプリケーションは作れるようになりました。

次回は、より複雑なアプリケーションを作成するためにv-ifなどのディレクティブについてお話したいと思います。

ありがとうございました。


2017年05月11日

SatoKeita

Vue.jsを使ってみよう その2

こんばんは、フリューのジョンです。最近Vue.jsを理解しようとVue.jsのソースコードリーディングをしています。

前回はVue.jsのかんたんな使い方とjQueryとの比較、などをお話しました。
今回はVue.jsの基本の話、elプロパティ、dataプロパティ、methodsプロパティの話をします。

Vue.jsのバージョンは2.3.0です。

elプロパティ

elプロパティはString型、または、HTML Elementである必要があります。
String型で与えた場合、document.querySelectorで存在した要素を使いますので、HTML Elementを与える必要はあまり無いと思われます。

コンパイル対象のルート要素に対して設定します。
コンパイルとは、データのバインディング設定などを行うフェーズです。
Vue.jsではルート要素以下の要素を網羅してHTMLを再構築しています。

dataプロパティ

dataプロパティはObject型、または、Object型を返すFunction型である必要があります。
後で説明するコンポーネントを使う場合、dataプロパティはFunction型でなければいけないので、常にFunction型を返すようにしておくほうが妥当だと思われます。

dataプロパティの値にはインスタンスからアクセスすることができます。また、HTML側からは直接アクセスすることが可能です。
さらに、Vue.jsはこのObject型に記述されたプロパティの変更を感知することができます。感知することで画面側の再描画が走ります。

このようにdataプロパティが返すObject型をいじると、再描画されているのがわかります。これは、Vue.jsがプロパティにsetterとgetterをつけており、その中で変更を検知しているためです。
しかし、配列の場合は少し勝手が違います。配列の中身をいじっても更新はされません。

もしこのような場合があれば次のように置き換えます。

vm.messages[0] = ‘ほげ’ → Vue.set(vm.messages, 0, ‘ほげ’)

またはspliceメソッドを用いてやります(spliceメソッドは再描画の検知ができます)

vm.messages[0] = ‘ほげ’ → vm.messages.splice(0, 1, ‘ほげ’)

(https://jp.vuejs.org/v2/guide/list.html#注意事項)

methodsプロパティ

methodsプロパティはプロパティがFunction型のObject型である必要があります。
methodsの各関数のthisはインスタンスがバインドされていますので、アロー関数を使わないようにしたほうが良いと思われます。

これらの関数にはdataプロパティと同じようにアクセスすることができます。

また、結果を返す関数も記述ができ、内部で使用しているプロパティが変更されると再描画されます。
しかし、この書き方は推奨されていません。全てのmethodsが自分が参照していないプロパティが変更されても、実行をしてしまうためです。

この問題を解消したい場合はcomputedプロパティを使いましょう。computedプロパティは後々お話します。

まとめ

Vue.jsの基本のプロパティの紹介とその使い方をご紹介しました。

次回は、HTML側について詳しく紹介したいと思います。

ありがとうございました。


2017年03月17日

araki

DroidKaigi 2017 に参加しました。会場の様子をレポートします!

コンテンツ・メディア第1事業部の荒木です。ピクトリンクというプリントシール画像を使ったアプリの Android 版を開発しています。

前回の記事では、DroidKaigi 2017 の参加前レポートを書きました。今回は、DroidKaigi 2017 の参加後レポートとなります。ほとんどのセッションはスライドと動画が公開されるようなので、この記事では DroidKaigi に参加できなかった方に向けて、会場の様子をお伝えします!

DroidKaigi とは?

※ 前回の記事と同じ内容を、再掲いたします。

公式サイト より引用:

DroidKaigiはエンジニアが主役のAndroidカンファレンスです。
Android技術情報の共有とコミュニケーションを目的に、2017/3/9(木)、3/10(金)の2日間開催します。

DroidKaigi とは、Android エンジニアのカンファレンスです。参加者は500人を超え、日本国内の Android カンファレンスとしては最大級の規模を誇ります。2015 年から開催されており、今回の DroidKaigi 2017 で3回目の開催となります。私は今回が初めての参加となります。

会場の様子

会場の様子をレポートいたします。今回の会場は、ベルサール新宿グランド コンファレンスセンターでした。

セッション

セッションルームは全部で6つありました。どのセッションも多くのエンジニアが発表を聞きに来ており、人気のセッションでは立ち見の人が出るほどでした。写真は Room3 の真ん中くらいから撮影したもので、私の後ろにもたくさんの聴講者がいました。

Session Room3

Session Room3 の様子

ランチ、おやつ

会場には、お菓子部屋がありました。各社のロゴの入ったお菓子や、マフィンなどがおいてあります。運営の方曰く、無限に湧いてくるとのことでした。

IMG_20170310_095808

 

他にも記念撮影スポットがあったり、

IMG_20170309_184112

 

バリスタの方がコーヒーを淹れてくれるというサービスもありました。常に長蛇の列ができていて、私は飲みそびれてしまいました。。

オフィスアワー

各セッションの後には、オフィスアワーが設けられました。オフィスアワーでは、発表者の方が質問やフィードバックを受けるために、お菓子部屋にしばらく滞在していました。発表者の周りには多くのエンジニアが集まり、発表内容について熱い議論を交わしていました。私もオフィスアワーで議論に参加したり、発表内容に関する疑問をぶつけてみたりしました。こうした貴重な経験は、カンファレンスに参加したからこそ得られるものだと感じました。

 

こちらのセッションのオフィスアワーで、MVVM について発表者の方と議論を交わしていました。とても楽しかったです!

アフターパーティー

全てのセッションが終わった後のアフターパーティーの様子です。ここでも、たくさんのエンジニアの方たちと交流することができました。

IMG_20170310_183106

 

寿司職人が握るお寿司。去年もあったそうです。大人気で、すぐに売り切れてしまいました。

IMG_20170310_191355

 

遠いですが、運営責任者の mhidaka さんが壇上にいらっしゃいます。この後、運営スタッフの方々に会場全体から感謝の拍手がありました。スタッフの方々のおかげでカンファレンス中、気持ちよく過ごすことができました。ありがとうございました!

IMG_20170310_202008

さいごに

今回は、DroidKaigi に参加できなかった方に向けて会場の様子をお伝えしました。楽しそうな雰囲気が伝わって「来年は DroidKaigi に参加するぞ!」と思っていただければ幸いです。私は来年も参加する予定ですので、ぜひみなさんも参加しましょう!