[Spring Security] Role Based Authorization - Spring Boot (3)

반응형

이번 글에서는 Spring Boot App에 Role Based Authorization을 적용하는 방법에 대해 알아보도록 하겠습니다.

1. Role Based Authorization

이번에는 이전글에서 생성한 spring boot app에 Role Based Authorization을 적용해보겠습니다.

앞서 생성했던 app에서는 사용자의 ROLE에 관계없이 모든 resource에 접근이 가능했습니다. 하지만, 실제 운영 환경에서는 사용자의 ROLE 별로 접근 가능한 resource가 달라야 하므로 이를 적용해보도록 하겠습니다.

1-1) overall

아래와 같이 SecurityConfiguration를 변경합니다.

SecurityConfiguration

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("admin123")).roles("ADMIN")
                .and()
                .withUser("user").password(passwordEncoder().encode("user123")).roles("USER")
                .and()
                .withUser("manager").password(passwordEncoder().encode("manager123")).roles("MANAGER");

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
        //.anyRequest().authenticated()
                .antMatchers("/index.html").permitAll()
                .antMatchers("/profile/**").authenticated()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/manager/**").hasAnyRole("ADMIN","MANAGER")
                .and()
                .httpBasic();
    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

이전글에서 달라진부분만 살펴보겠습니다.

1-2) AuthenticationManagerBuilder

configure(AuthenticationManagerBuilder auth)

 @Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     auth
             .inMemoryAuthentication()
             .withUser("admin").password(passwordEncoder().encode("admin123")).roles("ADMIN")
             .and()
             .withUser("user").password(passwordEncoder().encode("user123")).roles("USER")
             .and()
             .withUser("manager").password(passwordEncoder().encode("manager123")).roles("MANAGER");

}

• ADMIN/USER/MANAGER 계정을 생성했습니다.

1-3) HttpSecurity

configure(HttpSecurity http)

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
        //.anyRequest().authenticated()
                .antMatchers("/index.html").permitAll()
                .antMatchers("/profile/**").authenticated()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/manager/**").hasAnyRole("ADMIN","MANAGER")
                .and()
                .httpBasic();
    }

• anyRequest( ).authenticated( ) : 로그인한 모든 사용자는 모든 resource에 접근가능합니다. 이 부분은 ROLE Based Authorization과 충돌하는 부분이므로 주석처리합니다.

• antMatchers( ) : 해당 location과 일치하는 resource에 대한 접근 허용유무를 정의합니다.

• permitAll( ) : 모든 임의의 사용자들의 접근을 허용합니다. 로그인하지 않은 사용자도 접근할 수 있습니다.

• authenticated( ) : 로그인한 모든 사용자의 접근을 허용합니다.

• hasRole( ) : 로그인한 사용자 중 해당 ROLE을 가진 사용자만 접근을 허용합니다.

• hasAnyRole( ) : 로그인한 사용자 중 선언된 ROLE 중 하나이상의 ROLE을 가지고 있는 사용자만 접근을 허용합니다.

2. Test

이제 어플리케이션을 실행해보겠습니다.

앞서 .antMatchers("/index.html").permitAll( )로 모든 사용자가 index.html로 접근 가능하도록 허용했기 때문에, 로그인하지 않아도 정상적으로 index.html로 접근할 수 있습니다.

화면 상단의 Profile / Admin / Management를 클릭할 경우, 해당 location에 접근 가능한 ROLE을 소유한 user로 login 하지 않을 경우에는 위와 같이 접근이 제한됩니다.

3. Consideration

HttpSecurity 작성시 주의사항은 다음과 같습니다.

http request가 요청되었을때, spring은 request에 대한 접근제한을 위에서부터 순서대로 찾아내려옵니다.

따라서 맨위에 위와 같이 permitAll( )을 선언한경우 antMatchers( )로 선언한 접근제한자들이 더이상 작동하지 않습니다.

결론적으로 HttpSecurity 작성시에는 반드시 순서를 고려해 작성합니다. 😎


참고 자료 : https://www.youtube.com/playlist?list=PLVApX3evDwJ1d0lKKHssPQvzv2Ao3e__Q


추천서적

 

스프링5 레시피:스프링 애플리케이션 개발에 유용한 161가지 문제 해결 기법

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

댓글

Designed by JB FACTORY