Spring Securityを利用する
2022.02.25参考:http://terasolunaorg.github.io/guideline/current/ja/Security/Authentication.html
参考:https://codezine.jp/article/detail/11703
参考:https://spring.pleiades.io/projects/spring-security#learn
利用の開始
依存関係を追加する
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
}この状態で全てのルートでログインが必須になります
設定
WebSecurityConfigurerAdapterを継承したクラスを作成して、デフォルトbasic設定の書き換えを行います。
“/”はログイン不要でアクセスできるようにして、それ以外は認証必須としてみます。
package com.volkruss.misaka.web.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll() // "/"のアクセスは全て許可する
.anyRequest().authenticated() // 設定してないリクエストは認証が必要とする
;
}
}
DB認証をする
データーベースに登録されているユーザー情報でログインできるようにします。
UserDetailsServiceを実装したクラスにloadUserByUsernameメソッドをオーバーライドしてDBからユーザーを取得してorg.springframework.security.core.userdetails.Userクラスを返却します。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// dbからユーザーを取得する
User user = this.userRepository.findByUserName(username);
// ユーザーの権限を取得する
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("USER"));
// TODO 継承したログインユーザークラスの作成と返却を行う
return new org.springframework.security.core.userdetails.User(user.getUsername(),new BCryptPasswordEncoder().encode(user.getPassword()),authorities);
}
}
設定クラスのメソッドを修正します。ログインページまで見えなくなっているので、ログインページはアクセスできるようにします
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll() // "/"のアクセスは全て許可する
.anyRequest().authenticated() // 設定してないリクエストは認証が必要とする
// 以下修正(追加)
.and()
.formLogin()
.and()
.logout()
.permitAll();
http.httpBasic();
}
この状態でログイン画面(“/login”)からデータベースに登録しているユーザー名とパスワードでログインすると、ホーム画面に遷移でき、他のルートもアクセスできるようになります。
ロールの取得
現在はUSERロールを手動で付けていますが、こちらもデータベースから取得するようにします。
データベースから取得したロール情報からSimpleGrantedAuthorityを作成してGrantedAuthorityコレクションにaddします。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// dbからユーザーを取得する
User user = this.userRepository.findByUserName(username);
// ユーザーの権限を取得する
Collection<GrantedAuthority> authorities = new ArrayList<>();
//authorities.add(new SimpleGrantedAuthority("USER"));
List<Role> roles = this.roleRepository.getRoleByUserId(user.getId());
roles.forEach(role -> {
authorities.add(new SimpleGrantedAuthority(role.getName()));
});
// TODO 継承したログインユーザークラスの作成と返却を行う
return new org.springframework.security.core.userdetails.User(user.getUsername(), new BCryptPasswordEncoder().encode(user.getPassword()), authorities);
}
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll() // "/"のアクセスは全て許可する
.antMatchers("/system/**").hasRole("SYSTEM") // SYSTEMロールを持つユーザーのみ参照可能
.antMatchers("/admin/**").hasRole("ADMIN") // ADMINロールを持つユーザーのみ参照可能
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.permitAll();
http.httpBasic();
}
ADMINロールあり
SYSTEMロールなし
ロールによってページの参照権を操作できるようになります。