Spring Security를 처음 접하는 경우 권한 별 접근 제어는 대부분
WebSecurityConfigurerAdapter를 상속받은 클래스 하위에 configure(HttpSecurity http) 메서드에 설정하게 된다.
public class ServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final LoginService loginService;
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(this.adminServer.path("/"));
http.authorizeRequests(
(authorizeRequests) -> authorizeRequests.antMatchers("/assets/**").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
).httpBasic(Customizer.withDefaults())
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
new AntPathRequestMatcher("/api/v1/**"),
new AntPathRequestMatcher("/h2-console/**")
))
.headers().frameOptions().disable().and()
.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
}
}
이 설정 이외에 만약 특정 메서드에서 권한 별 접근 제어를 하고 싶은 경우에는 어떠한 방법이 있는지 알아보도록 하자.
Spring Security에서는 특정 Class, Method에 적용할 수 있는 Annotation을 제공한다.
해당 Annotation을 원하는 위치에 작성하면 해당 클래스 또는 메서드는 권한 체크하는 로직을 타게 된다.
Spring Security에서는 다양한 Annotation을 제공하는데, 오늘은 간단하게 @Secure, @PreAuthorize를 알아보도록 하자.
@Secured
@Secured는 특정 권한만 접근이 가능하다는 것을 나타내는 Annotation이다.
간단하게 특정 기능은 Admin만 이용하게 하고 싶은 경우 위의 Annotation을 붙여주면 된다.
public class ProjectController {
private final ProjectService projectService;
@PostMapping("/api/v1/project")
@Secured("ROLE_ADMIN")
public String save(@RequestBody ProjectSaveRequestDto requestDto) throws DuplicateException {
return projectService.save(requestDto);
}
}
만약에 단순하게 특정 권한을 가진 사람이 아닌 다양한 조건이 들어가야 되는 경우에는 @Secured로 표현하기는 조금 힘들게 된다.
이러한 경우에는 @PreAuthorize, @PostAuthorize를 이용하면 좀 더 복잡한 케이스도 처리할 수 있게 된다.
해당 Annotation에서는 SpringEL을 사용할 수 있어서 다양한 권한에 따른 처리가 가능하다.
Spring Expression Language에서는 다양한 Built-in expression을 제공한다.
아래의 예시에서는 " isAutheticated()" 를 사용하였다.
Spring EL에서 제공하는 Expression을 숙지하고 있으면 사용자가 직접 기능을 만들지 않고도 활용할 수 있어 유용하다.
@PreAuthorize("isAuthenticated() and (( #user.name == principal.name ) or hasRole('ROLE_ADMIN'))")
@RequestMapping( value = "", method = RequestMethod.PUT)
public ResponseEntity<Project> updateProject( User user ){
updateProject.update( user );
return new ResponseEntity<Project>( new Project(), HttpStatus.OK );
}
@PreAuthorize
추가적으로 @PreAuthorize 내에 #user.name를 사용한 부분을 보면
Annotation이 붙은 Method의 Param값을 위와 같이 활용하여 사용할 수 있게 된다.
@PostAuthorize
@PostAuthorize의 경우에는 Method가 실행된 이후의 return값을 활용할 수 있다.
아래와 같이 returnObject.name과 같이 "returnObject"를 사용하면 된다.
@PostAuthorize("isAuthenticated() and (( returnObject.name == principal.name ) or hasRole('ROLE_ADMIN'))")
@RequestMapping( value = "/{id}", method = RequestMethod.GET )
public Project getProject( @PathVariable("id") long id ){
return service.findOne(id);
}
Annotation 활성화 설정 추가
추가적으로, 이러한 Annotation을 활성화 시키기 위해서는 설정을 추가해 주어야 한다.
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final LoginService loginService;
@Override
protected void configure(HttpSecurity http) throws Exception {
//.....
}
}
'Spring > etc' 카테고리의 다른 글
[Spring] Spring Security Architecture (0) | 2021.11.29 |
---|---|
[Spring] @PreAuthorize, @PostAuthorize에서 Custom Security Expression 사용하기 (0) | 2021.11.27 |
[Spring] @WebMvcTest 작성 시 Spring Security 유의사항 (0) | 2021.09.29 |
[Spring] Controller Layer Test 코드 작성 (+예시) (0) | 2021.09.09 |
[Spring] Interceptor란 (+사용 예제) (0) | 2021.09.05 |