Spring Boot2.x에서 Spring Security를 이용해 권한을 관리 할 수 있다.
기본적으로 Override된 configure(HttpSecurity http)
에서 AntMatcher
를 이용해 Role확인을 할 수 있다.
하지만 관리 대상과 요구사항이 많아지면 Role만으로는 문제 해결이 용이하지 않다.
그래서 MethodSecurity
를 이용한 권한 관리 방법을 간략히 정리한다.
Gradle 설정
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.security:spring-security-oauth2-client")
compile("org.springframework.session:spring-session-jdbc")
Spring Security 설정 (SpringBoot 2.x 기준)
Spring Security와 관련된 코드는 기본적으로 아래처럼 할 수 있다.
설정 되어있다고 가정하고 넘어간다.
@EnableWebSecurity
public class ClientSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 생략..
}
}
GlobalMethodSecurity 설정
@EnableGlobaMethodSecurity
를 위 ClientSecurityConfig
에 추가해도 작동하지만
Class를 분리하여 ClientMethodSecurity
에 설정하기로 한다.
SpringBoot 2.x 기준
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ClientMethodSecurity extends GlobalMethodSecurityConfiguration {
}
SpringBoot 3.x 기준
Spring 6.0부터 @Bean 등록 방식으로 변경되었다.
@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
@Bean
protected MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
// 자세한 내용은 아래에
}
}
isAuthorized 사용
isAuthorized 등 annotation을 사용할 수 있다.
@GetMapping("/api/users/me")
@PreAuthorize("isAuthenticated()")
public UserResponse getMe(@AuthenticationPrincipal ExternalUser extUser) {
return userService.getMe(extUser.getId());
}
hasPermission 사용
hasPermission을 사용하려면 몇 가지 설정이 더 필요하다. permission을 evaluation할 수 있는 클래스를 만들고 GlobalMethodSecurity 설정에 연결 해야한다.
우선 PermissionEvalutor를 구현하는 클래스를 만든다.
public class ClientPermissionExpression implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
// 적절한 권한 관리 코드
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
// 적절한 권한 관리 코드
return false;
}
}
ClientMethodSecurity에 연결
SpringBoot 2.x 기준
그리고 나서 위의 클래스를 GlobalMethodSecurity에 연결한다. 그러므로 ClientMethodSecurity.java
내용은 이렇게 된다.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ClientMethodSecurity extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new ClientPermissionExpression());
return expressionHandler;
}
}
SpringBoot 3.x기준
@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
@Bean
protected MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new ClientPermissionExpression());
return expressionHandler;
}
}
컨트롤러 예제
이제 @PreAuthorize
에 hasPermission
을 사용할 수 있다. 두 가지 형태(method)가 존재한다.
- 아래는 게시물 Object에 권한이 있는지 확인하도록 하는 소스
@PreAuthorize("hasPermission('BBS', 'read')")
@GetMapping("/api/bbs/{name}")
public BbsResponse get(@PathVariable String name) {
// 생략
}
- 게시물 인자 name을 같이 넘겨 확인하는 소스
@PreAuthorize("hasPermission(#name, 'BBs', 'read')")
@GetMapping("/api/bbs/{name}")
public BbsResponse get(@PathVariable String name) {
// 생략
}
두 메소드가 ClientPermissionExpression.java
에서 만든 두 개의 메소드로 각각 호출 되기 때문에
마음에 드는 형태로 구현하면 된다.
DB에서 회원 id를 조회해서 권한이 있는지 확인 한다던지..
참고 링크
https://www.baeldung.com/spring-security-create-new-custom-security-expression
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client
'개발 > Java,Spring' 카테고리의 다른 글
Spring Boot 2.x에서 3.x로 업데이트 (0) | 2023.04.04 |
---|---|
Spring boot 2.4.5 @AuthenticationPrincipal occurs null (1) | 2021.04.30 |
우아한 테크세미나 - 스프링 배치 (3) | 2019.09.27 |
SpringSecurity에서 anonymous() (2) | 2019.08.15 |
SpringBoot Batch에서 JobParameter로 받을 수 있는 Type (4) | 2019.05.17 |