빙응의 공부 블로그
[Spring]스프링 시큐리티 - 구조 이해하기 본문
1편 안봤으면 보고오자, 간단한 개념을 설명하였다.
[Spring]스프링 시큐리티 - 개요 (tistory.com)
[Spring]스프링 시큐리티 - 개요
📝Spring Security Spring Security란 일반적인 공격에 대한 인증, 권한 부여 및 보호를 제공하는 프레임워크이다. 스프링 시큐리티의 기능은 크게 4가지로 나눈다. 인증(Authentication) 권한 부여(인가 : Auth
quddnd.tistory.com
📝Spring Security의 구조
스프링 시큐리티의 구조(아키택처)에 대해 알아보자
전에도 말했듯 스프링 시큐리티는 필터 기반의 기술이다.
필터 흐름
HTTP 요청 - WAS - 필터 - 서블릿 - 컨트롤러
🚩Spring Security 구조
1. 유저 자격을 기반으로 인증토큰(AuthenticationToken)만들기
- username과 passwerd를 요청(request)으로 추출하여 유저 자격을 기반으로 인증 객체를 생성한다.
- 이것을 UsernamePasswordAuthenticationToken이라 한다.
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
// 주로 사용자의 ID에 해당함
private final Object principal;
// 주로 사용자의 PW에 해당함
private Object credentials;
//-------------------------//
}
2. Fillter를 통해 AuthenticationToken을 AuthenticationManger에 위임한다.
- UsernamePasswordAuthenticationToken 오브젝트가 생성된 후, AuthenticationMangager의 인증 메소드를 호출한다.
- AuthenticationManager는 인터페이스로 정의되어있다.
- 실제 구현은 ProviderManager에서 한다.
- 너무 어렵게 생각하지 말자, 그냥 사용자를 검증하고, 인증을 성공하면 "Authentication" 객체를 반환한다.
//AuthenticationManager.java
public interface AuthenticationManager{
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
3. AuthenticationManager 가 인증을 수행한다.
- AuthenticationManager에 주어진 Authentication 객체를 기반으로 사용자를 검증하고 인증한다.
- AuthenticationManager의 구현체인 ProviderManager는 여러개의 AuthenticationManager를 관리하고 각각의 AuthenticationProvider에게 인증을 위임한다.
- 따라서 실제 인증과정은 AuthenticationProvider에서 수행하며, ProviderManager는 사실상 여러개의 인증을 관리하는 관리자 개념이다.
public class ProviderManager implements AuthenticationManager, MessageSourceAware,
InitializingBean {
public List<AuthenticationProvider> getProviders() {
return providers;
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
boolean debug = logger.isDebugEnabled();
//for문으로 모든 provider를 순회하여 처리하고 result가 나올 때까지 반복한다.
for (AuthenticationProvider provider : getProviders()) {
....
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
}
catch (AccountStatusException e) {
prepareException(e, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to
// invalid account status
throw e;
}
....
}
throw lastException;
}
}
4. UserDetailsService를 통한 UserDetails 객체 생성
- 인증에 성공하면 UserDetailsService는 UserDetails 객체를 생성한다.
- 이 객체는 Authentication 객체를 구현한 UsernamePasswordAuthenticationToken를 생성하기 위해 사용된다.
- 해당 객체는 사용자의 ID, 비밀번호 및 권한 등의 정보가 포함된다.
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
5. 인증 성공 후 인증된 사용자에 대한 보안 처리
- 사용자의 권한을 확인하고 접근 권한을 부여하는 단계이며 권한에 따라 보호된 리소스에 대한 접근을 제어한다.
참고! UserDetailsService 사용해보기
- UserDetailsService는 현재 로그인 사용자 정보를 불러올 수 있다.
- 밑에는 UserDetailsService의 원문이다.
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
이걸 이용해서 밑에 처럼 현재 로그인한 사용자의 정보를 쉽게 불러올 수 있다.
@Component
public class MemberComponent implements UserDetailsService {
private final MemberService memberService;
public MemberComponent(MemberService memberService) {
this.memberService = memberService;
}
@Override
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
Member member = memberService.findMemberById(id);
if (member == null) {
throw new UsernameNotFoundException("없는 회원입니다");
}
return User.builder()
.username(member.getId())
.password(member.getPw())
.build();
}
}
또한 컨트롤러에서는 이러한 방식으로 불러오면 된다.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String memberId = authentication.getName();
'Spring > 개인공부_이론' 카테고리의 다른 글
[Spring]예외 처리 전략 (0) | 2024.03.29 |
---|---|
JWT 개요 (0) | 2024.03.24 |
[Spring]스프링 시큐리티 - 개요 (0) | 2024.03.21 |
[Spring]타임리프(Thymeleaf)에 대해 알아보자! 2편 (1) | 2024.01.21 |
[Spring]타임리프(Thymeleaf)에 대해 알아보자! (0) | 2024.01.17 |