LoginSignup
18
21

More than 5 years have passed since last update.

spring-boot, security, socialでSign in with Twitterを実装する

Last updated at Posted at 2018-05-26

この記事で説明すること

spring-boot, spring-security, spring-socialを使ってソーシャルログインを実装したので、そのサンプルを利用してどのように実装したかを解説します。長くなると思うので自分が興味のあるChapterだけ選んで読んでみてください。

今回のサンプルでは、ソーシャルログインだけでなく、userid/passwordを入力してログインすることもできます。

経緯

spring-bootやspring-securityははじめてのSpring Bootで勉強した。
この本では、spring-boot, securityを使って、ログイン/ログアウトができる名簿アプリを作るのだが、そこに 「Sign in with Twitter」の機能も付けたくなり、つけようとしたが思いの外苦労してしまった…
私はこの苦労をこの世から根絶すべく、当記事の執筆に踏み切ったのである。

サンプルについて

ソースコード

こちらです。 https://github.com/PonzyPon/spring-boot-social-demo

サンプル君のできること

  • 独自のID/Passwordでログインできます
  • Twitterでログインできます
  • Twitterでログインした際にそれがそのユーザーにとって初めてのログインだった場合、裏で暗黙的にユーザー登録をします
  • ログインしたら、画面左上にそのユーザーの名前を表示できます
  • サーバー側ロジックで現在ログイン中のユーザーのUserIdを取得できます UserContext#getUserId

サンプル君のできないこと

  • ユーザー登録機能は実装していません。あらかじめV1__create-tables.sqlにてuser1というサンプルユーザーを作成しています

サンプル君のDB設計

このサンプルでは、独自ID/Passwordでのログインと、ソーシャルログインのどちらもを実現したかった。そのため2つのテーブルを作成した。ユーザーのマスタであるUserテーブルと、ソーシャルログイン情報を保持するUserConnectionテーブルである。User#user_idUserConnection#userIdは同じ物。この値を使って連結する。

User テーブル

カラム 補足
user_id VARCHAR primary key
username VARCHAR これもUNIQUE。
ログイン時にユーザーが入力する
display_name VARCHAR
encoded_password VARCHAR

UserConnection テーブル

カラム
userId VARCHAR
providerId VARCHAR
providerUserId VARCHAR
rank INT
displayName VARCHAR
profileUrl VARCHAR
imageUrl VARCHAR
accessToken VARCHAR
secret VARCHAR
refreshToken VARCHAR
expireTime BIGINT

このUserConnectionテーブルだが、実はもうこの構成はほぼ固定。このテーブルを操作するソースコードは自分では全く書いておらず、全てspring任せ。spring-frameworkにこんな感じでsqlのサンプルが提供されている。コピペして使おう。

ソースコード解説

spring-securityとspring-socialを使っている中でよく分からないのが俺の責務はどこだ?ということ。つまり、springがやってくれる部分と自分がやるべき部分との境界が分かりにくい。なのでその辺を含めて解説していく。

処理フローとその責任者

ユーザーログイン

UserをDBからロードする部分はspringはやってくれない。だからそこはUserDetailServiceというInterfaceを実装する必要がある。そうしておけば、その実装クラスが勝手に呼ばれてspringがUserのロード処理を行ってくれる。
UserDetailsServiceImplのソースはこちら

ユーザーログイン.png

ソーシャルログイン

ソーシャルログインの場合は、SNSアカウント情報を保持しているUserConnectionテーブルに対しての存在確認や、データの登録が必要となる。ただし、これは全てspringがやってくれる。我々開発者は、Userの作成処理と、そのUserテーブルからのロード処理をやってやればよい。
ConnectionSignUpImplのソースはこちら
SocialUserDetailsServiceImplのソースはこちら

ソーシャルログイン.png

その他のクラス

SignupServiceUserContextは必須ではない

基本的には最小構成でソーシャルログインのサンプルを作成しようとしているので、不要なクラスは無いが、例えばSignupServiceは作成しなくてもよい。このInterfaceは自分で作成したものだし、SignupServiceImpl#createUserの処理はConnectionSignUpImpl#executeに書いてしまってもよい。今回は、今後ユーザーの登録機能が付けば別クラスに分けることになるだろうと思ってクラスを分けただけ。
また、UserContextはログインユーザーのuserIdを簡単に取得できるよう作った便利クラス。無くてもソーシャルログインは動作する。

springの設定はSecurityConfigで

上でusernameとpasswordを受け取って認証する処理はspring任せという話をしたが、その設定はSecurityConfigで行っている。

解説はここまで。ここから下はサンプルの動かし方やいじくり方を説明します。

サンプル君の動かし方

(自分のtwitterアプリのConsumer KeyConsumer Secretがある方は3から)

  1. twitter でアプリを登録する (https://apps.twitter.com/)
    こんな感じで入力してください。
    twitter-app-create.png

  2. アプリをCreateしたら、twitter アプリのConsumer KeyConsumer Secretを( ..)φメモメモしておく
    2018-05-19_22h12_16.png

  3. git clone https://github.com/PonzyPon/spring-boot-social-demo.git

  4. src/main/resources以下のapplication.properties.sampleをコピーしてapplication.propertiesを作る

  5. application.properties内のspring.social.twitter.app-idspring.social.twitter.app-secretにそれぞれ上で( ..)φメモメモしたConsumer KeyConsumer Secretを書く

  6. プロジェクトのルート(pom.xmlがある場所)でmvnw spring-boot:runを実行する(mavenインストール済の人はmvn spring-boot:runでOK)

  7. localhost:7000にアクセスする

  8. (*^-^*)

(※もし、Twitterログイン時にエラーが出たらまずはTwitterアプリのCallback URL LockedをNoにしてみてください。それでダメならググって解決するしかないのです(^○^))

サンプル君のいじり方

Twitterでログインした後ツイートしたい

HomeController#writeTweetIdIfLoggedInWithTwitterというメソッドをデモ用に作成してあり、もしTwitterでログインしている場合は、そのアカウントのタイムラインの最新のつぶやきのtweetIdを取得しコンソールに書き出している。ここで使われているtwitter変数を使えばつぶやきも可能なのだ。サンプルとしてソースに書いてあるのでコメントアウトして試してみてほしい

HomeController#writeTweetIdIfLoggedInWithTwitter
// Hello!! とツイートする
twitter.timelineOperations().updateStatus("Hello!!");

現在ログインしているユーザーのIDを取得したい

UserContext#getUserIdを呼び出してくれ。誰もログインしていない場合もあるから、戻り値はOptional<String>だ。使うときはこんなイメージ。

public class Sample {
  @Autowired
  private final UserContext userContext;

  public Data getData() {
    dao.getData(userContext.getUserId().get());
  }
}

おわりに

このサンプルを作る前の自分が見たら嬉しくなるような記事をイメージして書きました。もし間違っているところや意見・質問あればよろしくお願いします。以上です。

18
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
21