목차
- [이론] 스프링 시큐리티 1
- [이론] 스프링 시큐리티2
- [실습] 스프링 시큐리티 Form Login
- [추가] CustomAuthenticationProvider vs DaoAuthenticationProvider
- [이론] 스프링 시큐리티3
- [이론] 스프링 시큐리티4
- [추가] AuthorizeReqeusts vs AuthorizeHttpRequests
- [실습] 스프링 시큐리티 Json data Login 처리
- [실습] 스프링 시큐리티 JWT 설정
- [실습] 스프링 시큐리티 JWT 처리
- OAuth2
서론
지금까지 인증(Authentication)에 대해 다뤄봤다면 이제는 권한 부여 즉 인가(Authorization)에 대해서 다뤄볼 차례이다
앞서서도 설명을 했지만 다시 한번 두개에 대해 말해보자면 다음과 같은 차이가 있다
- 인증: 접근하는 사용자가 누구인지 확인(현관문 벨을 눌렀을 때 '누구세요?'라고 묻기)
- 인가: 인증된 사용자에 대해서 권한을 확인하고 허락(누구인지 듣고 알고 있는 사람이라면 문 열어주기)
처음 Spring Security를 공부할 때 이 부분에 대해서 머리로는 이해하나 직접 작성하고 사용할 때에는 뭔가 혼란이 오기도 했다 꼭 차이를 알고 넘어가면 좋겠다
우리가 UsernamePasswordAuthenticationFilter
를 사용하여 인증에 대한 처리를 한 것 처럼 인가(Authorization)에 대해서도 AuthorizationFilter
가 존재하여 해당 필터에서 앞선 필터에서 제공하는 Authentication 객체를 사용하여 인가 처리를 하게 된다
GrantedAuthority
권한: 사용자가 시스템 자원을 사용하여 수행할 수 있는 작업
public interface GrantedAuthority extends Serializable {
String getAuthority();
}
이러한 권한은 UserDetails에서 사용한다
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
//생략
}
EndPoint 접근 설정
EndPoint는 Controller에 매핑하는 주소라고 생각하면 된다
이 부분에 대해서 설명이 되어있는 글 아래에 블로그 링크를 달아 뒀으니 확인해보면 되겠다
EndPoint 접근을 설정하는 방법에는 다음 두가지의 방법이 있다
- 권한: 읽기, 쓰기, 삭제 등
- 역할: User, Manager, 권한의 집합체라고 생각하면 된다
- user는 읽기 쓰기만 가능한 권한을 가진 역할
- manager는 읽기, 쓰기, 삭제가 가능한 권한을 가진 역할
우선은 모든 EndPoint에 대해서 설정을 해보자
특정 부분이 이난 모든 곳에 설정을 하고 싶으면 .anyRequest()
를 사용하면 된다
권한 기반 접근 설정
- hasAuthority(): 단일 권한
- hasAnyAuthority(): 복수 권한
@RequiredArgsConstructor
public class CustomUser implements UserDetails {
private final User user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(() -> "권한_작성");
}
//생략
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.anyRequest()
.hasAuthority("권한_작성");
http.authorizeHttpRequests()
.anyRequest()
.hasAnyAuthority("권한_작성1", "권한_작성2", ...);
return http.build();
}
UserDetails에 관한 객체 생성시 권한_작성 부분에 원하는 권한의 이름을 작성을 하면 된다
현 예시에는 객체 자체에 작성을 해 생성되는 모든 user에 대하여 동일한 권한을 주게 되지만 각 다른 권한을 주기 원한다면 AuthenticationProvider에서 반환하는 객체에 대해서 적용을 해주게 되면 된다
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getPrincipal().toString();
UserDetails user = userService.loadUserByUsername(username);
if (passwordEncoder.matches(password, user.getPassword())) {
return new UsernamePasswordAuthenticationToken(
user.getUsername(),
user.getPassword(),
user.getAuthorities() // DB에 저장된 권한 가져옴
);
}
throw new BadCredentialsException("BAD Credentials");
}
}
역할 기반 접근 설정
권한 기반 설정과 거의 모든 것이 똑같고 설정시 사용되는 메소드만 다르다
- hasRole()
- hasAnyRole()
EndPoint 설정
위 코드에서 anyRequest
부분을 변경해주면 된다
mvcMathcers() 권장
경로별, HttpMethod + 경로별로 적용할 수 있다
- 해당 경로 이하의 모든 경로를 표시할라면 ** 접미사 사용 ex) /user/**
- @pathVariable 사용시 ex) /user/{pathVariableName: 정규식}
antMatchers()
경로별, HttpMethod + 경로별, HttpMethod별로 적용할 수 있다
작성된 경로 그대로만 접근 설정이 된다
antMathcers("/a").authenticated()
와 같이 설정을 하였을 때 /a
에 대해서는 권한이 요구되지만 /a/
에 대해서는 요구되지 않는다
이러한 문제점 때문에 가능하면 mvcMathers()를 사용하는 것을 권장한다
regexMatchers()
정규식을 사용해서 경로를 지정하는 것인데 가능하면 사용하지 말자
혹시라도 위의 두개로도 해결이 안 될때 그때 찾아서 사용하는 것으로 하자
정규식을 조금이라도 잘못 작성하게 되면 찾기 어려운 오류로 화면을 만나게 될 것이다
참고 링크
'공부기록 > Spring Security' 카테고리의 다른 글
[추가] AuthorizeRequests vs AuthorizeHttpRequests (0) | 2022.12.28 |
---|---|
[이론] 스프링 시큐리티4 (0) | 2022.12.28 |
[추가]CustomAuthenticationProvider vs DaoAuthenticationProvider (0) | 2022.12.22 |
[실습] 스프링시큐리티 로그인처리 (2) | 2022.12.21 |
[이론] 스프링 시큐리티2 (1) | 2022.12.21 |