인가 적용 시점
Authentication 객체의
- Collection<? extends GrantedAuthority> getAuthorities(); 메서드를 구현하면 권한을 담아 둘 수 있다.
기타 필드 값
- detail : User에 대해 담을 정보들의 객체
- principal : pk 값
- isAuthenticated : 인증 여부에 대한 참, 거짓 값
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
구현체
@Getter
@Setter
@RequiredArgsConstructor
public class MyTokenAuthentication implements Authentication {
private final String token;
private MyTokenPayload payload = new MyTokenPayload();
private boolean authenticated = false;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return payload.getRoles().stream()
.map(SimpleGrantedAuthority::new)
.toList();
}
@Override
public Object getCredentials() {
return null;
}
@Override
public MyTokenPayload getDetails() {
return payload;
}
@Override
public Long getPrincipal() {
return payload.getUserId();
}
@Override
public String getName() {
return payload.getUsername();
}
}
SecurityConfig의 SecurityFilterChain
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtFilter jwtFilter) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(request ->
request
.requestMatchers(jwtUtil.allowedUrls).permitAll()
.requestMatchers("/api/admin/**").hasAuthority("ROLE_GREEN")
// .requestMatchers("/api/admin/**").hasAnyRole("GREEN")
.anyRequest().authenticated())
.sessionManagement(sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session을 사용하지 않음
)
.addFilterBefore(jwtFilter, RequestCacheAwareFilter.class)
.build();
}
Autority(권한)와 Role(역할)은 두 가지 다 접근을 막는 역할을 한다. 둘의 차이는 아래와 같다.
- Autority(권한) 은 접근자에 따른 행위를 제한시킬 때 사용한다.
- Role(역할)은 User를 역할로 나누어 둔다(예시 관리자, 구매자, 판매자) 이를 기반으로 행위를 제한 시킨다. 역할을 정의할 때에는 접두사로 ROLE_로 시작해야 한다.
접근자에 따른 행위를 제한시키킬때 사용되는 메서드
- 권한 : hasAuthority(), hasAnyAuthority()
- 역할 : hasRole(), hasAnyRole()
타 블로그등 정리된 글을 참고하였을땐 위 두 메서드 모두 파라미터에 "ROLE_"를 붙이지 않아도 자동으로 붙기에 적지 않아도 된다는 글을 많이 보았다.
하지만 필자가 사용하고 있는 SpringSecurity3.2.2 버전에선 hasRole(), hasAnyRole() 메서드는 ROLE_을 생략하고도 작동하였으나 hasAuthority(), hasAnyAuthority() 는 정확한 문자열을 입력해야("ROLE_" 포함) 작동되는 것을 확인하였다.
아마 권한과 역할을 동시에 Authority 컬렉션에 저장한 후 위에 설명한 두 메서드의 역할을 구분 지어 사용할 수 있게 함이 아닐까 조심스럽게 추측해 본다.
public final class AuthorityAuthorizationManager<T> implements AuthorizationManager<T> {
private static final String ROLE_PREFIX = "ROLE_";
public static <T> AuthorityAuthorizationManager<T> hasRole(String role) {
Assert.notNull(role, "role cannot be null");
Assert.isTrue(!role.startsWith(ROLE_PREFIX), () -> role + " should not start with " + ROLE_PREFIX + " since "
+ ROLE_PREFIX + " is automatically prepended when using hasRole. Consider using hasAuthority instead.");
return hasAuthority(ROLE_PREFIX + role);
}
public static <T> AuthorityAuthorizationManager<T> hasAuthority(String authority) {
Assert.notNull(authority, "authority cannot be null");
return new AuthorityAuthorizationManager<>(authority);
}
//... 이하 생략
}
'Spring' 카테고리의 다른 글
공공데이터 Springboot로 파싱 (0) | 2024.04.13 |
---|---|
Security CORS 설정 (0) | 2024.03.17 |
Mappstruct 사용 (0) | 2024.03.11 |
SpringSecurity 프로젝트 적용 (0) | 2024.03.03 |
SpringSecurity 인증 방식 (0) | 2024.03.02 |