3

私はJava/Spring/MVCに比較的慣れていません。この問題は解決されずにさらに別の週末を台無しにしようとしているので、誰かがこれに光を当ててくれることを願っています.

現在、いくつかの RFC を実装するプロジェクトに取り組んでいます。各 RFC には、Hibernate クエリやストアド プロシージャの変更から、テキストのマイナーな変更やフォームへのフィールドの追加に至るまで、独自の「課題」があります。

私が今直面している問題は、Spring のセキュリティに関係していると思います。

現状:
アプリケーションにログインするために、ユーザーはログイン ページ (/user/login.jsp) によって提示されます。ユーザー名とパスワードを入力すると、ウェルカム ページ (/welcome/hello.jsp) が表示されます。

ユーザーがパスワードを忘れた場合、新しいパスワードを入力できるページ (/welcome/newPassword?code=xxx) へのリンクを提供する電子メールを送信するリンクを使用します。[送信] ボタンを入力すると、いくつかの検証が行われ、パスワードがデータベースに保存され、ページに「パスワードが変更されました」というメッセージが表示されます。アプリケーションに入るには、ユーザーは新しいパスワードでログインする必要があります。

顧客の要望: 新しいパスワードを送信すると、ユーザーは新しいパスワードで自動的にログインし、/welcome/hello.jsp にリダイレクトされます。

Web を検索しましたが、探していたシナリオが見つかりませんでした (または、認識できなかった可能性があります!)。

私がトリックを行うと思ったこと:

現在、新しいパスワードを処理する WelcomeController にこのメソッドがあります。

@RequestMapping(method = RequestMethod.POST)
public void newPassword(Model model, HttpSession httpSession, ModelAttribute(PASSWORD) Passwords password, BindingResult result) {
    logger.debug("Posting password for new password");
    ScreenMessage message = null;

    //
    try {
        // errors from initBinder - back to page
        if (result.hasErrors()) {
            return;
        }

        // Validate input: on error go back to form
        passwordValidator.validate(password, result);
        if (result.hasErrors()) {
            return;
        }

        // Save password
        passwordService.createNewOwnPassword(result, password);
        if (result.hasErrors()) {
            return;
        }

        // No errors
        message = new ScreenMessage();
        message.setText(CHANGED);
        message.setArg(THIS_PASSWORD, 0);
        model.addAttribute(MESSAGE, message);
        httpSession.setAttribute(ACTION_READ, Boolean.TRUE);

        // Errors are fatal.
    } catch (Exception e) {
        logger.error("ERROR-CHANGE-password for user: " + password.getUser().getLoginName(), e);
        result.reject(  ERROR_FATAL, new Object[] { password}, ERROR_FATAL);
    } finally {
        model.addAttribute(PASSWORD, password);
    }
}

このメソッドを単純に変更して、ModelAndView を返してリダイレクトを使用できるようにできると思いました。

ModelAndView mav = new ModelAndView("redirect:/welcome/hello", (ModelMap) model);
        return mav; 

しかし:それは私を/ user / loginに送り続けます。まさに私が行きたくないページです...

便利な追加情報:

私が知る限り、アプリケーションは Spring 2.5 を使用しています。

(関連があるといいのですが)私のsecurity-applicationContext.xmlの一部:

    <!--  always-use-default-target="true" -->
    <security:form-login login-page="/dyn/user/login" 
        login-processing-url="/dyn/user/j_spring_security_check"
        default-target-url="/dyn/welcome/hello" 
        always-use-default-target="true"
        authentication-failure-handler-ref="exceptionTranslationRouting" />

    <security:access-denied-handler error-page="/dyn/welcome/hello" />

    <security:logout logout-success-url="/dyn/user/logout" invalidate-session="true" />

/welcome/hello にリダイレクトするという私の考えは単純すぎるのでしょうか、それとも小さな何かが欠けているだけなのでしょうか?

4

1 に答える 1

1

まず、ロジックを Web コントローラー (パスワードの検証は好きではありません) からパスワード変更専用のコンポーネントに移動することをお勧めします。これにより、アプリケーションの一部を論理的に分離できます。もしかしてフィルター?(後ほど) それとも特別サービス?

次に、Spring Security のソース コードを見てみましょう。私の経験から言えば、Spring Security のカスタマイズは、そのアーキテクチャ (特にフィルター チェーン) を理解している場合にのみ可能です。class をご覧になることをお勧めしますAbstractAuthenticationProcessingFilter。アプリケーションでユーザー名とパスワードを提供するときにユーザーを認証する責任があります。メソッドを見てくださいAbstractAuthenticationProcessingFilter.successfulAuthentication

そのメソッドのこの行は、ユーザーをログインさせるセキュリティ コンテキストを設定します。

 SecurityContextHolder.getContext().setAuthentication(authResult);

参照 authResult のタイプはAuthenticationです。これは、インスタンスによって実装されるインターフェイスUsernamePasswordAuthenticationTokenです。UsernamePasswordAuthenticationFilter.attemptAuthenticationそのようなオブジェクトを構築する方法の例としてメソッドを見てください。

フィルター ソリューションに戻る: 個人的には、拡張する独自のフィルターを実装することを考えますAbstractAuthenticationProcessingFilter。パスワードの変更を担当します。そうすれば、認証成功時のセッション変更などについて考える必要がありません。XML に挿入するだけです。

総括する、

参照することをお勧めするクラス:

  • AbstractAuthenticationProcessingFilter
  • UsernamePasswordAuthenticationToken
  • UsernamePasswordAuthenticationFilter

Spring Security Documentation、特にアーキテクチャー、フィルターチェーン、およびユーザー認証におけるその役割に関する部分を読む必要があります。

http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#overall-architecture

于 2012-11-03T21:52:27.157 に答える