質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.79%

Twitter4jを使用したTwitterログインについて

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 774

flumchaso

score 11

前提・実現したいこと

Twitter4jを使用して、ログイン処理を実施しようとしています。
以下に記載のソースコードが現在の実装です。
知恵をお持ちの方はご教示いただければと思います。

該当のソースコード

  • TwitterService.java
   /**
     * Twitter連携の認証画面を表示するためのrequestTokenを取得する。
     */
    @Override
    public RedirectView getTwitterRequestToken() {

        RedirectView redirectView = new RedirectView();

        Twitter twitter = new TwitterFactory().getInstance();
        twitter.setOAuthConsumer(socialConfig.getTwitterApiKey(), socialConfig.getTwitterApiSecret());

        try {
            RequestToken requestToken = twitter.getOAuthRequestToken(socialConfig.getTwitterCallbackUrl());

            //SocialSessionにRequestTokenとTwitterの情報を格納する。
            session.setRequestToken(requestToken);
            session.setTwitter(twitter);

            redirectView.setUrl(requestToken.getAuthenticationURL());
        } catch (TwitterException te) {
            //エラーがあった場合、エラーの情報を乗せてリダイレクト。
            if (te.getErrorCode() == UNAUTHORIZED) {
                redirectView.setUrl(appHostUrl + TWITTER_REDIRECT_PATH);
                redirectView.setAttributesMap(
                        new HashMap<String, String>() {{
                            put("code", String.valueOf(te.getErrorCode()));
                        }}
                    );
            }
        }
        return redirectView;
    }

    /**
     * Twitter認証画面からのコールバック処理
     * @throws Exception
     */
    @Override
    public RedirectView accessTwitter(String oauthToken, String oauthVerifier) throws Exception {

        RedirectView redirectView = new RedirectView();

        //認証を許可しなかった場合は、TOPに遷移する。
        if (oauthVerifier == null) {
            redirectView.setUrl(appHostUrl);
            return redirectView;
        }

        try {
            AccessToken accessToken = session.getTwitter().getOAuthAccessToken(session.getRequestToken(), oauthVerifier);

            //取得したTwitterのユーザ情報から自サービスのユーザ情報を取得する。
            Optional<User> optionalUser = userRepository.findByTwitterUserId(
                    accessToken.getUserId());

            if (!optionalUser.isPresent()) {
                //ユーザ情報がない場合、新規登録します。ただし、同名のuserKey(TwitterのScreenName)のデータがある場合はエラーとします。
                Boolean userFlag = userRepository.existsByUserKeyAndDeleteFlag(
                        accessToken.getScreenName(), Boolean.FALSE);
                if (userFlag) {
                 //エラーがあった場合、エラーの情報を乗せてリダイレクト。
                    redirectView.setUrl(appHostUrl + TWITTER_REDIRECT_PATH);
                    redirectView.setAttributesMap(
                            new HashMap<String, String>() {{
                                put("code", String.valueOf(code));
                            }}
                        );
                    return redirectView;
                }
                twitter4j.User twitterUser = session.getTwitter().showUser(accessToken.getUserId());

                String thumbnail = twitterUser.get400x400ProfileImageURL();

                User newUser = new User(
                        UUID.randomUUID().toString(),
                        twitterUser.getName(),
                        accessToken.getScreenName(),
                        twitterUser.getEmail(),
                        thumbnail,
                        Boolean.FALSE);
                userRepository.save(newUser);

                optionalUser = userRepository.findByTwitterUserId(
                        accessToken.getUserId());
            } else {
                //すでに登録されているユーザの場合は、ユーザ情報からログインします。
            }
        } catch (TwitterException te) {
            if (te.getErrorCode() == UNAUTHORIZED) {
                redirectView.setUrl(appHostUrl + TWITTER_REDIRECT_PATH);
                redirectView.setAttributesMap(
                        new HashMap<String, String>() {{
                            put("code", String.valueOf(SOCIAL_LOGIN_API_ERROR_CODE));
                        }}
                    );
            }
        } catch (final Exception exception) {
            LOGGER.error(ErrorMessageEnum.INTERNAL_SERVER_ERROR.getSystemMessage(), exception);
            redirectView.setUrl(appHostUrl + TWITTER_REDIRECT_PATH);
            redirectView.setAttributesMap(
                new HashMap<String, String>() {{
                    put("code", String.valueOf(SOCIAL_LOGIN_API_ERROR_CODE));
                }}
            );
        }
        return redirectView;
    }
  • SocialSession.java
@Data
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@SuppressWarnings("serial")
public class SocialSession implements Serializable {

    private Twitter twitter;
    private RequestToken requestToken;

}

発生している問題・エラーメッセージ

accessTwitterのメソッドで、サーバが1台の場合は問題ないのですが、複数に分散させた場合RequestToken、Twitterの情報を自作のsocialSessionクラスに持たせているため、認証画面で許可をした後に違うサーバへ向いてしまった際にNPEが発生してしまいます。
この際に、何かいい解決策はないでしょうか?

補足情報(FW/ツールのバージョンなど)

Java:8
Spring Boot:2.0.4
Twitter4j:4.0.7

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

自作のsocialSessionクラスに持たせているため

SpringSessionを使い、Redisを導入し、Redisをセッションストアに指定するのが一番簡単でしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る