1. ホーム
  2. java

[解決済み] Spring Security / SpringMVCで認証済みユーザーを手動で設定する方法

2022-05-14 04:47:52

質問

新規ユーザーが「新規アカウント」フォームを送信した後、そのユーザーを手動でログインさせ、その後のページでログインする必要がないようにしたいのですが、どうすればよいでしょうか。

Springセキュリティインターセプターを経由する通常のフォームのログインページは問題なく動作します。

new-account-formコントローラでUsernamePasswordAuthenticationTokenを作成し、それをSecurityContextに手動で設定しています。

SecurityContextHolder.getContext().setAuthentication(authentication);

その同じページで、私は後でユーザーがログインしていることを確認します。

SecurityContextHolder.getContext().getAuthentication().getAuthorities();

これで、先ほど認証で設定した権限が返ってきました。すべて順調です。

しかし、この同じコードが次に読み込んだページで呼び出されると、認証トークンはUserAnonymousだけになっています。

なぜ、前のリクエストで設定した認証が保持されないのか、よくわかりません。何か考えがありますか?

  • セッション ID が正しく設定されていないことと関係があるのでしょうか。
  • 何らかの方法で認証を上書きしている可能性はありませんか?
  • おそらく、認証を保存するために別の手順が必要なのではないでしょうか?
  • あるいは、単一のリクエストではなく、セッション全体にわたって認証を宣言するために、何らかの方法で行う必要があるのでしょうか?

ここで何が起こっているかを見るのを助けるかもしれない、いくつかの考えを探しています。

どのように解決するのですか?

私もしばらく前にあなたと同じ問題に直面しました。詳細は覚えていませんが、次のコードでうまくいきました。このコードは Spring Webflow フロー内で使用されるため、RequestContext と ExternalContext クラスが使用されます。しかし、あなたに最も関連する部分は、doAutoLoginメソッドです。

public String registerUser(UserRegistrationFormBean userRegistrationFormBean,
                           RequestContext requestContext,
                           ExternalContext externalContext) {

    try {
        Locale userLocale = requestContext.getExternalContext().getLocale();
        this.userService.createNewUser(userRegistrationFormBean, userLocale, Constants.SYSTEM_USER_ID);
        String emailAddress = userRegistrationFormBean.getChooseEmailAddressFormBean().getEmailAddress();
        String password = userRegistrationFormBean.getChoosePasswordFormBean().getPassword();
        doAutoLogin(emailAddress, password, (HttpServletRequest) externalContext.getNativeRequest());
        return "success";

    } catch (EmailAddressNotUniqueException e) {
        MessageResolver messageResolvable 
                = new MessageBuilder().error()
                                      .source(UserRegistrationFormBean.PROPERTYNAME_EMAIL_ADDRESS)
                                      .code("userRegistration.emailAddress.not.unique")
                                      .build();
        requestContext.getMessageContext().addMessage(messageResolvable);
        return "error";
    }

}


private void doAutoLogin(String username, String password, HttpServletRequest request) {

    try {
        // Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
        token.setDetails(new WebAuthenticationDetails(request));
        Authentication authentication = this.authenticationProvider.authenticate(token);
        logger.debug("Logging in with [{}]", authentication.getPrincipal());
        SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (Exception e) {
        SecurityContextHolder.getContext().setAuthentication(null);
        logger.error("Failure in autoLogin", e);
    }

}