前回は「spring-boot-starter-security」が提供してくれるBASIC認証をやってみたので、今回は、自分でログイン機能を作ってデータベース認証をやってみたいと思います!, 何が違うかというと、ログインを許可するユーザとパスワードを設定ファイルではなく、DBに持たせることができるので、汎用性が高くなります。, BASIC認証だと、みんな同じユーザIDとパスワードを使うことになりますし、セキュリティはガバガバですね, プロトタイプなんかで、かつIPアドレスが絞れないような環境でクライアント認証させたいようなシステムだと結構このBASIC認証は簡単に実装できるので威力を発揮するんじゃないかなーと思ってます。, ちなみに、今回はDBにH2を使用してデータベースアクセスにはMyBatisを使います, こやつが新参者で、何をしているかというとSpringフレームワークがもつ機能の設定をいじってるって感じです。, @Configurationアノテーションでこのクラスは設定情報を記述しているんですよ!とSpringに教えています。, 続く@EnableWebSecurityってのは、SpringSecurityが提供しているConfigurationクラスをインポートし、SpringSecurityを利用するために必要となるコンポーネントのBean定義を自動で行われるようにするものです, で、UserServiceっていうサービスクラスをDIしている。このクラスについては後述する, こいつは、入力されたパスワードをエンコードするクラスでSpring側のライブラリ。, @Beanアノテーションをつけて、DIコンテナにこのエンコードクラスを登録してます。, こいつは、スーパークラスの「WebSecurityConfigurerAdapter」が持ってるメソッドで、最初のauthorizeRequests().anyRequest().authenticated()ってとこはよーわからん!笑, で、次のformLogin().loginPage(“/login”) ってとこは、formLoginメソッドを呼び出すことで、フォーミ認証を有効にしており、FormLoginConfigurerのインスタンスが返ってきます。このインスタンスには、フォーム認証で使用するコンポーネントの動作をカスタマイズするためのメソッドが定義されており、その1つがloginPageメソッドです。このメソッドでフォーム認証に使用するフォームが存在する認証画面は「/login」ってパスやでってことを指定しています。, で、次のloginProcessingUrlメソッドが引数に指定した「/sign_in」ってパスにリクエストがあったら、「username」と「password」のパラメータを使って認証をかけます!成功したらsuccessForwardUrlメソッドの引数に指定している「/hello」ってパスにフォワードして、, 失敗したらfailureUrlで指定している「/login」ってパスにerrorっていうパラメータつけて返します。, 続く、permitAllメソッドは、すべてのユーザに対してログインフォームへのアクセス権を付与するためのメソッドです。, で、次のlogout().logoutUrl(“/logout”).logoutSuccessUrl(“/login?logout”)てのが, ログアウト用のパスは「/logout」でここにリクエストが来たらセッション破棄など認証情報を初期化して「/login」ってパスにlogoutっていうパラメータをつけて返します。, ちなみに、SpringSecurityでは、以下のような流れでログアウト処理を行う, ・クライアントは、ログアウト処理を行うためのパスにリクエストを送信する。ここでいう「/logout」のこと, ・LogoutFilterは、LogoutHandlerのメソッドを呼び出してログアウト処理を行う, ・LogoutFilterは、LogoutSuccessHandlerのメソッドを呼び出して画面遷移を行う。, .logoutメソッドを呼び出すことで、ログアウト機能が有効になり、LogoutConfigurerのインスタンスが返されます。, こいつは、configureってメソッドをDIしてて認証処理をごにょごにょしてます。笑, このuserDetailsServiceってのもSpring側のライブラリで、このクラスを継承した独自クラスを作成する必要があります。後述!, 次は、本サイトにアクセスがあった場合にlogin画面を返す必要があるのでその設定です, addViewControllersの引数で取得したクラスのaddViewControllerメソッドを呼びます。この引数にはパスを指定し、続くsetViewNameにhtmlファイル名を書きます。, はい、こいつのメソッドはDBへデータを更新するため@Transactionalアノテーションをクラス全体につけます, で、実際にMyBatisを使ってデータアクセスをするDAOクラスをDIしています。こいつは後述, 注目すべきは、「UserDetailsService」っていうSpring側のライブラリクラスを実装していて、loadUserByUsernameメソッドをオーバーライドしています。, UserDetailsServiceは資格情報とユーザの状態をデータストアから取得するためのインターフェースで、以下のメソッドが定義されている。, このメソッドの最初でMyBatisを使ってユーザ名と一致するデータを取得しエンティティクラスであるLoginUserクラスに情報を格納して返します。, データベースに情報が見つからなかったら例外を吐きます。この結果がWebConfigSecurityクラスの, 今回は権限テーブルとしてUSERテーブルを作ります!このテーブルにユーザ名とパスワードを登録しておくことで、認証が成功するという仕組みです!, 最後の部分はエンコードクラスをインスタンス化してDBから取得したパスワードをエンコーディングさせ、ユーザ名、パスワード、権限リストをそれぞれフィールドに持ったUserクラスをUserDetailsインターフェースに格納して返します。, BCryptPasswordEncoderは、BCryptアルゴリズムを使用してパスワードのハッシュ化およびパスワードの照合を行う実装クラスで、ソルトには16バイトの乱数が使用され、デフォルトでは、1024回ストレッチングを行っているみたい。, ※ソルト:パスワードに追加する文字列のこと。パスワードにソルトを追加して実際のパスワードより桁数を長くすると、レインボークラックなどのパスワード解析を困難にすることができる。, ※ストレッチング:ハッシュ値の計算を繰り返し行うこと。ストレッチングを多く行いパスワード解析に必要になる時間を増やすと、パスワードの総当たり攻撃などによるパスワード解析を困難にすることができる。この回数は多いほど、強度はますがサーバへの負荷は高くなる。, ちなみに、SpringSecurityには、BCrypt以外にStandardPasswordEncoderとNoOpPasswordEncoderがあり、どれもPasswordEncoderの実装クラスです。, StandardPasswordEncoderは、SHA-256アルゴリズムを使用してパスワードのハッシュ化および照合を行う。, NoOpPasswordEncoderは、ハッシュ化をしません。テスト用のクラスとして用意されているので、実際のアプリケーションで使用することはないですね!, ちなみに、このUserクラスとUserDetailsインターフェース両方ともSpring側のライブラリです。, UseDetailsは、認証処理で必要となる資格情報(ユーザIDとパスワード)とユーザの状態を提供するためのインターフェースで、以下のメソッドが用意されている, で、SpringSecurityでは、UserDetailsの実装クラスとしてUserクラスを提供している, データ永続化関連なので@Repositoryアノテーションをつけていて、LoginMapperインターフェースをDIしています。, findUserメソッドで引数に受け取った(フォームから送られてきたもの)ユーザ名を使用して、データを取得します!, 何の変哲もないクラスですね。あ、@Mapperアノテーション関連の説明は「SpringBootでMyBatis使ってみた」記事で解説しているのでよかったらみてください。, いいですね。user_name(引数で受け取ったもの)を使ってデータを検索していますl, 次に、USERテーブルに認証を許可するユーザ名とパスワードを登録するdata.sqlを同じくresources直下に保存します, WebConfigSecurityクラスにて認証が成功したら「/hello」にフォワードするため、それを受け取るハンドラーが必要になります, ちなみに、このリクエストハンドラーが呼ばれるということは認証が成功しているということになります。, SpringSecurityのデフォルト実装では、認証済みのユーザの認証情報は、セッションに格納される。セッションに格納された認証情報はリクエストごとにSecurityContextPersistenceFilterクラスによってSecurityContextHolderというクラスに格納され、同一スレッド内であれば、どこからでもアクセスすることができます。. » 運営者情報 Clipping is a handy way to collect important slides you want to go back to later. Copyright © Yoshikazu Nojima 2018 You can change your ad preferences anytime. * Web全般のセキュリティ そして、対象(セキュアオブジェクト)に対して現在のユーザーがアクセスの権限があるかどうかを、各 AccessDecisionVoter にチェック(投票)させる。 * 未認証エラーを返す。 Now customize the name of a clipboard to store your clips. セッション管理の話 ROLEカラムなど、権限の値で制御を行った方が良い、という事でしょうね。, xmlによってauthenticationManagerのidを複数にし、ちゃんとBean設定してあげれば、行けるっぽい。 ある決まった特定の振る舞いを持つが、その振る舞いのバリエーションが多様な場合。 6.2.1.1. Remember-Me の話 ※動作確認のための簡易実装のためコンテナから明示的に PasswordEncoder を取得しているが、実際はコンテナ管理の Bean に PasswordEncoder を DI するなどして参照を得ることになる, ログイン後 http://localhost:8080/xxxx/encode-password?password=fuga にアクセス(コンテキストパスは適宜置き換え)。, Spring Security を構成する重要なクラスの1つに Authentication が存在する。 No public clipboards found for this slide. このメソッドは GrantedAuthority のコレクションを返却する。, GrantedAuthority もインターフェースで、名前の通り「ユーザーに付与された権限」を表している。 想定読者 1.1. デフォルトでは上述のようにテーブル・カラムを宣言すると、自動的にユーザー情報が検索されるようになる。, ファイルはクラスパス配下に配備されるようにしておく(あとでデータソースを作るときに初期化スクリプトとして使用する), 引数でユーザーを識別するための文字列(普通はログイン画面などで入力されたユーザー名)が渡ってくるので、その識別文字列に対応するユーザー情報を返却する。, この条件には Spring 独自の式言語である SpEL (Spring Expression Language) を使用する。, you can read useful information later efficiently. */, /** ", org.springframework.security.core.authority.AuthorityUtils, org.springframework.security.core.userdetails.User, org.springframework.security.core.userdetails.UserDetails, org.springframework.security.core.userdetails.UserDetailsService, org.springframework.security.core.userdetails.UsernameNotFoundException, "sample.spring.security.MyUserDetailsService", "org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder", "$2a$08$CekzJRYhb5bzp5mx/eZmX.grG92fRXo267QVVyRs0IE.V.zeCIw8S", org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder, org.springframework.security.crypto.password.PasswordEncoder, org.springframework.web.context.WebApplicationContext, org.springframework.web.context.support.WebApplicationContextUtils, org.springframework.security.core.Authentication, org.springframework.security.core.GrantedAuthority, org.springframework.security.core.context.SecurityContextHolder, org.springframework.security.web.authentication.WebAuthenticationDetails, org.springframework.security.web.DefaultRedirectStrategy, org.springframework.security.web.RedirectStrategy, org.springframework.security.web.authentication.AuthenticationSuccessHandler, "sample.spring.security.handler.MyAuthenticationSuccessHandler", sample.spring.security.handler.MyAuthenticationSuccessHandler, org.springframework.security.core.AuthenticationException, org.springframework.security.web.authentication.AuthenticationFailureHandler, "sample.spring.security.handler.MyAuthenticationFailureHandler", sample.spring.security.handler.MyAuthenticationFailureHandler, "isAuthenticated() and hasAuthority('USER')", "sample.spring.security.expression.MyExpression", sample.spring.security.expression.MyExpression, org.springframework.security.access.AccessDecisionVoter, org.springframework.security.access.ConfigAttribute, "org.springframework.security.access.vote.AffirmativeBased", "org.springframework.security.web.access.expression.WebExpressionVoter", "sample.spring.security.voter.AcceptFugaVoter", org.springframework.security.access.AccessDecisionManager, org.springframework.security.access.vote.AffirmativeBased, org.springframework.security.web.access.expression.WebExpressionVoter, sample.spring.security.voter.AcceptFugaVoter, "org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl", "org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler", org.springframework.security.access.expression.SecurityExpressionHandler, org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl, org.springframework.security.web.FilterInvocation, org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler, "org.springframework.security.access.vote.RoleHierarchyVoter", "org.springframework.security.access.vote.AuthenticatedVoter", org.springframework.security.access.AccessDeniedException, org.springframework.security.web.access.AccessDeniedHandler, "sample.spring.security.handler.MyAccessDeniedHandler", sample.spring.security.handler.MyAccessDeniedHandler, デバイスでのパフォーマンス分析を自動化する新しいツールArm Mobile Studio, TERASOLUNA Server Framework for Java (5.x) Development Guideline — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.3.0.RELEASE documentation, java - Difference between Role and GrantedAuthority in Spring Security - Stack Overflow.