私はプログラムによる手動のユーザーログインを実装するためにスプリングセキュリティを使用しています。私はユーザーのアイデンティティを積極的に確立し、ログインしたいというシナリオを持っています。私はパスワードを知らないので、フォームをURLに送信する通常のログインコードパスを使用できません。サーブレットFilter
で傍受し、すべての認証+セッション魔法を実行します。スプリングセキュリティマニュアルのログインのベストプラクティス
私が検索した、そしてほとんどの人が自分のAuthentication
オブジェクトを作成しているようだし、その後経由でおよそ春を告げる:この作品、
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(user, "", user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
。 Springはそれを私のためにセッションに入れて、後続のHTTPリクエストが認証ステータスを維持するようにします。
しかし、これは汚れたハックだと感じます。私は手動ログインを達成するために、コントローラ内部でsetAuthentication()
の使用に関連する問題の具体的な例を与えることを願っていますいくつかの詳細を提示します:
アイデアを与えるために、私の設定は次のとおりです。
httpSecurity
.authorizeRequests()
.antMatchers("/test/**").permitAll()
.antMatchers("/admin/**", "/api/admin/**").hasRole("USER_SUPER_ADMIN")
.and()
.formLogin()
.loginPage("/sign-in?sp")
.loginProcessingUrl("/api/auth/sign-in")
.successHandler(createLoginSuccessHandler())
.failureHandler(createLoginFailureHandler())
.permitAll()
.and()
.logout()
.logoutUrl("/api/auth/sign-out")
.logoutSuccessHandler(createLogoutSuccessHandler())
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry)
;
キー上記のポイント:
- フォームのログインにカスタム成功と失敗のハンドラーを使用する
- ユーザーあたりの最大同時セッションの動作を設定したい
- 私は春のデフォルトのセッション固定保護を維持したいログイン)。
- 私はセッションレジストリを使用したい
- ...詳細、私はそれを設定しましたか?
私はスプリングを使ってフォームのログインを処理する方法を確認しました。予想どおり、Springは私のHttpSecurity
configがフォームログインを使用するときに指示したすべてのことを行います。しかし、SecurityContextHolder.getContext().setAuthentication()
で自分のカスタム/手動ログインを行うと、それはありません。これは、Springがサーブレットの内部にあるauth + sessionの内容をすべて処理するためです。Filter
と私のプログラムコードで実際にはFilterを呼び出すことはできません。さて、不足している振る舞いを自分自身で追加して、コードを複製してみることができます.FilterはConcurrentSessionControlAuthenticationStrategy
、ChangeSessionIdAuthenticationStrategy
、およびRegisterSessionAuthenticationStrategy
を使用しています。これらのオブジェクトを自分で作成し、設定し、カスタムログイン後に呼び出すことができます。しかし、それはそのような形でそれを複製するのはちょっと残念です。さらに、私は行方不明の他の行動がある - 私は、フォームのログインコードパスを使用すると、その春は、私は私のカスタムログインを行うときにトリガされないいくつかのログインイベントをトリガ気づいた。おそらく私が紛失しているか、理解していない他のものがあります。全体のプロセスはかなり複雑です。
私は間違った方法でこれに近づいているように感じます。 私は春が私にとって大切なものを迂回しないように、別の戦略を使用すべきですか?多分私はこのカスタムログインを達成するために私自身のAuthenticationProvider
を作るべきですか?
*明確にするために、私のコードは多かれ少なかれ動作します。しかし、私は貧しい戦略を使ってそれを達成したように感じます。なぜなら、私にとっては春がやる多くのものを複製するコードを書く必要があったからです。さらに、私のコードは、春のことを完全に再現するわけではありません。プログラムでログインを達成するには、より良い方法が必要です。
を使用するには、AuthenticationProvider
コンフィグ春のセキュリティそれは広すぎるようだが。問題に関する適切な情報を提供するためにコンテンツを減らすことができますか?[MCVE](https://stackoverflow.com/help/mcve)を投稿してください。 –
@dur私のカスタム(手動)ログインは、最初のアカウント作成直後に使用されます。彼らに電子メールを送り、彼らのアカウントを確認するためのリンクをクリックさせる。リンクをクリックすると、資格情報を再入力せずにログインします。このシナリオでは私はパスワードを持っていないので、 'ActiveDirectoryLdapAuthenticationProvider'のような「通常の」春の認証メカニズムを使うことはできません。パスワードを忘れてしまった場合でも、基本的には同じことをやります。パスワードを変更したりリセットしたりすることなく、アカウントのアクセスを制限することができます。これは私のユースケースにとって非常に重要です。 – goat
@dur、さらに、*パスワードを持っていても、春になると私のためにすべてのことをやり遂げることはできません。なぜなら、春はサーブレット 'Filter'の魔法ですアプリケーションコード(コントローラなど)が実行される前に私は、ログイン状態とそれに関連付けられたセッションのすべてをプログラマチックにリストアップする呼び出しを行う必要があります。 – goat