質問: Spring Security 使い方メモ 認証・認可 - Qiita > > * UserDetailsService を実装したクラスを作成する。 > * UserDetailsService には loadUserByUsername(String) というメソッドが1つだけ存在する。 > + 引数でユーザーを識別するための文字列(普通はログイン画面などで入力されたユーザー名)が渡ってくるので、その識別文字列に対応するユーザー情報を返却する。 > + 対応するユーザー情報が存在しない場合は UsernameNotFoundException をスローする。 > > > UserDetailsService (spring-security-docs-manual 5.3.3.RELEASE API) > > Locates the user based on the username. In the actual implementation, the search may possibly be case sensitive, or case insensitive depending on how the implementation instance is configured. In this case, the UserDetails object that comes back may have a username that is of a different case than what was actually requested.. > > >
回答: 回答順が前後しますが、 > > username の情報だけに基づいて検索して良いんでしょうか?パスワードによる認証をしている場合は、パスワードが一致していることの担保は別の機構(おそらく`HttpSecurity`で内部的に?)で行っているのでしょうか? > > > What is a UserDetailsService and do I need one?曰く: > > `UserDetailsService` is a DAO interface for loading data that is specific to a user account. It has no other function other to load that data for use by other components within the framework. It is not responsible for authenticating the user. > > Authenticating a user with a username/password combination is most commonly performed by the `DaoAuthenticationProvider`, (後略) > > > (22.7.4. Common "Howto" Requestsにある`UserDetailsService`についての疑問と回答も参照してみてください。`UserDetailsService`とは何であるか、というのがより理解できるかなと思います。) ということで、`UserDetailsService`とはまさに「usernameの情報だけに基づいて検索」するための機構です。 また、Spring Securityにおいて認証処理を実装するところは`AuthenticationProvider`ですが(詳しくはこちらの回答でもリンクしているSpring Security Architectureなどを参照してください)、`UserDetailsService`においては、引用文中にある通り、デフォルトでは`DaoAuthenticationProvider`が利用されるようになっています。 > > なぜUserDetailsServiceを実装して、loadUserByUsernameメソッドで username に基づいたユーザーを返す必要があるのでしょうか? > > > これについては、そのようなシチュエーションに適すように設計されたものだから、としか答えようがないかと思います。 必要がある、わけではなくてusername(ユーザのユニークキー(自然キー))でユーザ検索するのが普通だからそういう設計になっている、ので、ここにギャップがあるなら`UserDetailsService`を利用すべき状況ではないということになります。 > > principal と credentials は2つそろうことで機能すると思うので、パスワードによる認証を行っていた場合、どのような機構で、この2つを担保しているのでしょうか? > > > こちらについては疑問に感じられているポイントがわかりませんでした(& princpalとcredentialsに誤解があるように思われます)。 `UsernamePasswordAuthenticationFilter`と`DaoAuthenticationProvider`(及びその親クラス`AbstractUserDetailsAuthenticationProvider`)の実装を見ることで解決するでしょうか。 (以下、回答とは直接関係ない余談です) `UserDetailsService`というのは(おそらくは多くの初学者の予想に反して)Spring Securityの応用的な使い方です。 なので、`UserDetailsService`を用いたサンプルを以てSpring Securityの基本を学ぼうとするのはハードルが高い(し、遠回りだ)と個人的には感じています。 できれば`UserDetailsService`を利用していないコードサンプルから始められた方が良いのではないかな、と私は考えます。 (しかし、世に溢れる初心者向けと称するコードサンプルは`UserDetailsService`を使ったものばかり...というのに自分が学び始めた頃にも感じてQiitaに書きなぐったりもしたのですが。) 追記: ...なので自分で(私のQiitaの記事としては比較的真面目に)書いてみました。 サンプルコードはこちらです。