Hello

권한 설정(feat. @PreAuthorize, @PostAuthorize)

by 볼빵빵오춘기
더보기

SpringSecurity를 사용할 때 SecurityConfig 클래스를 만들어 filterChain() 메소드안에서 특정 url이 요청이 들어왔을 때 해당 권한이 있는 사용자만 접근 가능하도록 설정을 했었다. 

하지만 그 외에도 특정 url이 붙지않아도 설정 해주고 싶을 때가 있을 수 있다. 

그럴 때 Controller에서 특정 url에만 해당 권한이 있는 사용자만 접근하도록 설정해보자!

@Configuration //
@EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true) // controller에 권한설정
public class SecurityConfig{
 
    @Autowired
    private PrincipalOauth2UserService principalOauth2UserService;
 
    private final PrincipalDetailsService userDetailsService;
 
    public SecurityConfig(PrincipalDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
 
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
 
    @Bean
    public BCryptPasswordEncoder encodePwd() {
        return new BCryptPasswordEncoder();
    }
 
    @Bean public LoginSuccessHandler loginSuccessHandler(){
        return new LoginSuccessHandler();
    }
 
    @Bean
    public LoginFailureHandler loginFailureHandler(){
        return  new LoginFailureHandler();
    }
 
 
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
 
        http.formLogin((formLogin) ->
                        formLogin.loginPage("/loginForm").loginProcessingUrl("/login").successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler()))
                .authorizeHttpRequests(authorize ->
                authorize
                        .requestMatchers("/login").permitAll() // 추가부분
                        .requestMatchers("/user/**").hasAnyRole("USER","SHELTER","ADMIN") // /user/** url => user, center, admin  권한이 있는 사용자만 접근 가능
                        .requestMatchers("/center/**").hasAnyRole("CENTER","ADMIN") // /center/** url => center, admin  권한이 있는 사용자만 접근 가능
                        .requestMatchers("/admin/**").hasAnyRole("ADMIN") // /center/** url => admin  권한이 있는 사용자만 접근 가능
                       .anyRequest().permitAll() // 권한을 주지않은 url 이 아니면 접근 허용
        ).oauth2Login((oauth2) -> oauth2
                        .loginPage("/loginForm").userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint
                                .userService(principalOauth2UserService)).successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler())) ;
 
        http.csrf(CsrfConfigurer::disable).cors(Customizer.withDefaults());
 
        return http.build();
    }
 
}

 

@PreAuthorize & @PostAuthorize

  • Spring Security에서 메서드 수준에서 권한을 제어하기 위해 사용하는 어노테이션이다.
  • 어노테이션을 사용하면 특정 메서드가 호출되기 전(@PreAuthorize)이나 호출된 후(@PostAuthorize)에 접근을 제어한다.

 

@PreAuthorize

메서드 실행 전에 접근 권한을 제어하고 싶을 때 사용한다.

주로 메서드 인자나 현재 인증된 사용자의 권한을 기반으로 접근을 제한한다.
ex) 특정 역할을 가진 사용자만 특정 메서드를 실행할 수 있도록 하거나, 특정 사용자만 자신의 데이터에 접근할 수 있도록 할 때 사용한다.

 

@PreAuthorize 사용방법

Security 설정 클래스에 메서드 보안 활성화

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // Security 설정 클래스에 메서드 보안 활성화
public class SecurityConfig {
    // 기타 보안 설정
}

 

메서드에 @PreAuthorize 어노테이션 추가

@Service
public class PreAuthorizeService {

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void adminMethod() {
        // 관리자만 접근 가능한 로직
    }

    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
    public void userOrAdminMethod() {
        // 사용자 또는 관리자 접근 가능한 로직
    }

    @PreAuthorize("#username == authentication.name")
    public void userSpecificMethod(String username) {
        // 메서드 인자와 인증된 사용자 이름이 일치해야 접근 가능한 로직
    }
}

 

@PostAuthorize

  • 메서드 실행 후 반환된 결과를 기반으로 접근 권한을 제어하고 싶을 때 사용한다.
  • 주로 메서드 실행 결과에 따라 접근을 제한하고자 할 때 사용한다.
    ex) 메서드가 반환한 객체의 특정 필드 값이 현재 인증된 사용자와 일치하는지 확인하는 경우에 사용한다.

 

@PostAuthorize 사용방법

Security 설정 클래스에 메서드 보안 활성화

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // Security 설정 클래스에 메서드 보안 활성화
public class SecurityConfig {
    // 기타 보안 설정
}

 

메서드에 @PostAuthorize 어노테이션 추가

@Service
public class PostAuthorizeService {

    @PostAuthorize("returnObject.owner == authentication.name")
    public SampleObject findSampleObjectById(Long id) {
        // 메서드 실행 후 반환된 객체의 소유자와 인증된 사용자가 일치해야 접근 가능한 로직
        return sampleObjectRepository.findById(id);
    }
}

 

 

정리하자면

어노테이션을 적절히 활용하면, 애플리케이션의 메서드 수준에서 보다 세밀한 접근 제어를 구현할 수 있다.

 

 

블로그의 정보

Hello 춘기's world

볼빵빵오춘기

활동하기