はじめに
概要
WeekendEngineerというグループの中で9月にPlayFrameworkを使ったTwitterツールの開発をしました。
その時に勉強した技術の一つである「PlayFrameworkでTwitter4jを使ったOauth認証とAPIの利用方法」について説明をします。
Playframework/ScalaとTwitter4jでOAuthログインするサンプルにも記事がありましたが、Play2.6に対応していないようなので、僭越ながらScala初心者がPlay2.6ver.でお送りします。
コードの全容はこちらのリポジトリにあります。
controllers.auth.AuthController
今回のプログラムで実現していること
- Twitterアカウントでログインをする
- ログインしたアカウントでツイートを投稿する
環境
MacOSX
Intellij
Java 10
sbt 0.13.17
scala 2.12.2
playframework 2.6.19
手順
参考→Playframework/ScalaとTwitter4jでOAuthログインするサンプル
Twitter4jプラグインを依存ライブラリに追加
今回はTwitter4jプラグインを使ってTwitterのAPIを叩きます。
以下を追記して、プラグインをインポートします。
// https://mvnrepository.com/artifact/org.twitter4j/twitter4j-core
libraryDependencies += "org.twitter4j" % "twitter4j-core" % "4.0.4"
Twitterアプリケーションを登録
- 開発者アカウントの作成 開発者向けTwitterページにアクセスして、Twitterでログインをする。
- 新規Twitterアプリの作成
アプリ作成ページにアクセスして、アプリの登録をしましょう。
sign in with twitterを有効化して、callback先URLに「http://127.0.0.1:9000/callback」を指定します。
認証用のControllerを用意
Oauthは以下のようなフローで実現されます。
- Twitterの認証ページにリダイレクトする。
- ユーザがTwitterアカウントでログインをする。
- Twitterからユーザのトークンとともにアプリケーションへリダイレクトされる。
こちらで用意するのは、以下2つのアクションです。
- Twitterの認証ページにリダイレクトする「loginアクション」
- Twitterからのリダイレクトの受け口になる「callbackアクション」
AuthControllerクラスを作成
app>controllersにAuthControllerを作成し、
SyncCacheApiをDIします。
@Singleton
class AuthController @Inject()(cc: ControllerComponents, cacheApi: SyncCacheApi) extends AbstractController(cc) {
}
loginアクションを実装
def login = Action {implicit request =>
// twitter4jのtwitterインスタンスを取得
val twitter: Twitter = (new TwitterFactory()).getInstance()
// twitterからリダイレクトするURL(twitterアプリ作成時に指定したURL)を指定して、リクエストトークンを取得
val requestToken: RequestToken = twitter.getOAuthRequestToken("http://127.0.0.1:9000/callback")
// cacheにtwitterとrequestTokenを保存
cacheApi.set("twitter", twitter, 120)
cacheApi.set("requestToken", requestToken, 120)
// Twitterの認証ページにリダイレクト
Redirect(requestToken.getAuthorizationURL)
}
twitter4j.propertiesを作成
confディレクトリにtwitter4j.propertiesを作成し、twitterアプリページのkey and tokenタブにあるconsumer keyを転記します。
oauth.consumerKey=twitterアプリのAPIkey
oauth.consumerSecret=twitterアプリのAPI secret key
routesにGET /login controllers.auth.AuthController.login
を追記すれば、http://127.0.0.1/loginを叩いてTwitterの認証ページにアクセスできるはずです。
callbackアクションの作成
login時に保存したrequestToken
とtwitterからのリクエストに保存されたoauthVerifier
を使用して、ユーザのアクセストークンを取得しています。
def twitterOAuthCallback = Action { implicit request =>
// TwitterのオブジェクトをCacheから取得
val getTwitter : Option[Twitter] = Option(cacheApi.get("twitter"))
// 取得できない場合はトップ画面へ
getTwitter match {
case Some(twitter) => {
// RequestTokenのオブジェクトをCacheから取得
val getRequestToken: Option[RequestToken] = Option(cacheApi.get("requestToken"))
// 取得できない場合はトップ画面へ
getRequestToken match {
case Some(requestToken) => {
// authVerifierを取得する
var authVerifier: String = request.queryString.get("oauth_verifier").get.head
// AccessTokenを取得する
val accessToken: AccessToken = twitter.getOAuthAccessToken(requestToken, authVerifier)
cacheApi.set("accessToken", accessToken, 4320)
// Twitterオブジェクトの認証
twitter.verifyCredentials()
// Cacheに認証情報を保存(私はTwitterSessionクラスのインスタンスを生成し、保存しました。)
val twitterSession: TwitterSession =
new TwitterSession(accessToken.getToken, accessToken.getTokenSecret, accessToken.getScreenName)
cacheApi.set("twitterSession", twitterSession, 4320)
// 不要なのでCacheから削除
cacheApi.remove("twitter")
cacheApi.remove("requestToken")
}
case _ =>
}
}
case _ =>
}
Redirect("/")
}
routesにGET /callback controllers.auth.AuthController.callback
を追記すれば、Oauthログインができているはずです。
APIを使用する
Twitterクラスのインスタンスを生成するときに、Oauthで取得したAccessTokenを突っ込むだけで、TwitterAPIを使えます。以下の例はツイートを投稿するUpdateStatusというメソッドを使っている例です。
@Singleton
class Twitter4JClient{
/**
* TweetをPostする.
* @param accessToken
* @param tweetText
* @throws TwitterException
* @return
*/
def updateStatus(token: String, secret: String, tweet: Tweet): Tweet = {
val accessToken: AccessToken = new AccessToken(token, secret)
val twitter: Twitter = (new TwitterFactory()).getInstance(accessToken)
try {
val status: Status = twitter.updateStatus(tweet.getBody())
return Tweet(status.getText, status.getUser.getScreenName)
} catch {
case e:TwitterException => throw e
}
}
}