[Spring Security] Spring Boot를 이용한 Role Based Authorization

dev-log·2021년 10월 2일
3
post-thumbnail

1. Role Based Authorization

이전에 생성한 spring boot에 Role Based Authorization을 적용한다. (이전에 생성한 app은 여기에서 확인할 수 있다.)

앞서 생성한 app은 사용자의 role에 관계없이 모든 resource에 접근이 가능하다.
하지만 실제 운영 환경에서는 사용자의 role에 따라 접근 가능한 resource가 달라야 하므로 이를 적용해 보려 한다.

1-1) 전체 코드

아래와 같이 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("/management/**").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("/management/**").hasAnyRole("ADMIN","MANAGER")
                .and()
                .httpBasic();
    }

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

• antMatchers( ) : 특정경로를 지정한다.
( /** : 경로의 모든 하위 경로(디렉토리) 매핑한다.)

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

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

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

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

HttpSecurity 주의 사항

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

따라서 .anyRequest().permintAll()을 .antMachers(특정페이지)보다 먼저 선언한경우 antMatchers( )로 선언한 접근제한자들이 더이상 작동하지 않는다.

💫따라서 HttpSecurity 작성시에는 반드시 순서를 고려해야 한다.💫

2. 실행 화면

Home화면은 .antMatchers("/index.html").permitAll()로 모든 사용자가 접근이 가능하도록 했기 때문에 로그인하지 않아도 페이지를 볼 수 있다.

로그인하지 않은 상태에서 다른 Tab(Profile/Admin/management)을 클릭하면 로그인 화면이 나온다.

로그인에 성공하면 각자 권한에 맞는 페이지는 정상적으로 출력되고

권한이 없는 페이지는 이렇게 빈 페이지 화면이 출력된다.

Reference

이번 글은 바보개발님의 글의 참고해 작성됐습니다. ✨

https://minholee93.tistory.com/entry/Spring-Security-Role-Based-Authorization-Spring-Boot-3

profile
배운 걸 기록하는 곳입니다.

0개의 댓글