簡易的ですが、Spring Security + RBAC のサンプルを作りました。
kntmr/playground/spring-security-rbac - GitHub
今回、User と Role は 1 対 1 にしています。あと、Thymeleaf 側では、Permission (hasAuthority
) ではなく、あえて Role (hasRole
) を使っているところがあります。RBAC ならすべて Permission に寄せるべきだろうとは思いますが、今回はサンプルなので...。
というわけで、UserDetailsService#loadUserByUsername
では、権限と Prefix 付き (ROLE_*
) の Role を UserDetails
に渡しています。これで hasAuthority
と hasRole
を使い分ける。
@Transactional @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByName(username); return new org.springframework.security.core.userdetails.User( user.getName(), user.getPassword(), AuthorityUtils.createAuthorityList( Stream.concat( Stream.of(user.getRole().nameWithPrefix()), // Prefix を付けて返す user.getRole().getPermissions().stream().map(Permission::getName)).toArray(String[]::new))); }
WebSecurityConfigurerAdapter#configure
はふつう。and()
でメソッドチェーンするより分割して書いた方が見やすい気がする。なるほど。
@Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/login") .usernameParameter("username") .passwordParameter("password") .defaultSuccessUrl("/", true) .permitAll(); http.logout() .logoutUrl("/logout") .logoutSuccessUrl("/") .permitAll() .invalidateHttpSession(true); http.authorizeRequests() .mvcMatchers("/admin/**").hasAuthority("WRITE") .anyRequest().authenticated(); }