ログインユーザ情報の構成
SecurityContextHolder | SecurityContextを保持する |
SecurityContext | セキュリティに関わる情報を保持する |
Authentication | 認証トークンを保持する |
Principal | ログインユーザ情報を保持する |
Credentials | ユーザID、パスワード等を保持する |
Authorities | 権限情報を保持する |
基本的な認証に必要な設定あれこれ
SecurityConfigファイル
SecurityConfigファイルのサンプル
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
// 認証項目カスタマイズ時は指定
@Autowired
@Qualifier("UserDetailsServiceImpl")
private UserDetailService userDetailsService
// 独自のログイン認証を実装する場合は指定
@Autowired
@Qualifier("TestAuthenticationProvider")
private AuthenticationProvider authenticationProvider
@Override
protected void configure(HttpSecurity http) throws Exception{
//ログイン認証不要なページ、直リンク禁止ページを設定
http
.authorizeRequests()
//ログイン無しでアクセスOK
.antMatchers("/login").permitAll()
//上記以外はログインが必要
.anyRequest().authenticated();
//ログイン処理
http
.formLogin()
//ログイン処理時のパス
.loginProcessingUrl("/login")
//ログインページの指定
.loginPage("/login")
//ログイン失敗時の遷移先
.failreUrl("/login?error")
//ユーザIDパラメータ名 ※login.htmlのnameに指定
.usernameParameter("userId")
//パスワードパラメータ名 ※login.htmlのnameに指定
.passwordParameter("password")
//ログイン後の遷移先
.defaultSuccessUrl("/home")
//(カスタマイズ)ログイン後の遷移先を制御 ※別途クラス作成が必要
.successHandler(successHandler)
//ログアウト処理
http
.logout()
//ログアウト処理時のパス
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
//ログアウトページの指定
.logoutUrl("/logout")
//ログアウト後の遷移先
.logoutSuccessUrl("/login");
}
// 認証項目カスタマイズ時は指定
@Orverride
protected void configure(Authentication ManagerBuilder auth) throws Exception{
// 1.独自のログイン認証を実装しない場合且つ、ログイン処理時のユーザ情報をDBから取得する場合
auth.userDetailService(userDetailsService).passwordEncoder(passwordEncoder());
// 2.独自のログイン認証を実装する場合
auth.authenticationProvider(authenticationProvider)
}
}
ログイン画面のコントローラー
コントローラークラスのサンプル
@Controller
public class LoginController{
@GetMapping("/login")
public String init(){
return "login";
}
}
ログイン後遷移先のコントローラー
コントローラークラスのサンプル①
@Controller
public class HomeController{
@GetMapping("/home")
public String init(Model model, Principal principal){
// SecurityContextHolderからユーザ情報を取得する
Authentication authentication = (Authentication) principal;
User user = (User) authentication.getprincipal();
/** ログイン後の任意処理 */
// user.toString()でユーザ情報を取得可能
return "home";
}
}
@AuthenticationPrincipalを使用することでUser情報取得を省略可能
コントローラークラスのサンプル②
@Controller
public class HomeController{
// ※
@GetMapping("/home")
public String init(Model model, @AuthenticationPrincipal User user){
/** ログイン後の任意処理 */
// user.toString()でユーザ情報を取得可能
return "home";
}
}
指定しているUserクラスはSpringのクラス。カスタマイズする場合は変更が必要
ログイン後のhtml画面
sec:authentication属性で、ユーザIDなら「name」、ロールなら「principal.authorities」でユーザ情報を取得可能
home.html
//省略
// ユーザIDの取得
<p>ユーザID:<span sec:authentication="name"></span>
// ロールの取得
<p>ロール:<span sec:authentication="principal.authorities"></span>
// 認証項目カスタマイズ時は指定
<p>ユーザID:<span sec:authentication="principal.username"></span>
<p>任意項目:<span sec:authentication="principal.[userDetailsの実装クラスに指定したフィールド]"></span>
//省略
独自ユーザクラスの作成
UserDetailsクラス
DBからユーザを取得する際は下記のクラスを使用
DaoAuthenticationProvider | DBからユーザを取得して認証処理を行うクラス。Authentication、Principalにユーザ情報を設定する。パスワードチェックもこのクラスが提供する。 |
UserDetailsService | ユーザIDからユーザ情報を取得するインターフェース。このクラスを実装したクラスでDB取得処理を実装し、独自ユーザクラスを生成する。 |
UserDetails | ユーザクラス用のインターフェース。このクラスを実装したクラスが独自ユーザクラスとなる。 |
UserDetaiols:userNameフィールドはSpringのデフォルトでユーザIDとしてみなされるため注意
独自のログイン認証を実装
通常、ログインIDとパスワードで認証をおこなうところ、テナントIDなども認証項目として利用したいケース。
AuthenticationFilter | URLリクエストに対し、Authentication(認証情報)を作成。それをAuthenticationManagerに渡して、認証処理を呼び出す。 |
AuthenticationManager | AuthenticationProviderを管理。認証処理自体はAuthenticationProviderで実行される。複数のAuthenticationProviderを順番に呼び出し、一つでも認証成功となれば認証OKとなる。 |
AuthenticationProvider | 認証処理を実装する。 |
AuthenticationProviderのサンプル
@Component("TestAuthenticationProvider")
public class TestAuthenticationProvider implements AuthenticaitonProvider {
/** 認証処理を実装 */
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 独自の認証処理を実装
// UsernamePasswordAuthenticationTokenには権限のsetterがないため、新たなインスタンスを生成する。
return new UsernamePasswordAuthenticationToken(principal, credentials, authorities)
}
/** 認証対象のクラスを制限するためのメソッド。
* 今回は[UsernamePasswordAuthenticationToken]だけを認証対象にしている
*/
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAddignableForm(authenticaiton);
}
}