[12.23] 내일배움캠프[Spring] TIL-38
1. SpringSercurity
동작원리
Spring Security
는 요청이 들어오면 Servlet Filter Chain
을 자동으로 구성한 후 거치게한다.
Filter Chain
: 여러 Filter
를 Chain
형태로 묶어 놓은 것
Filter
: Tomcat
과 같은 웹 컨테이너에서 관리되는 서블릿의 기술( 내가 아는 Tomcat
은 내장 서버로써 Response
와 Request
를 담당하는 부분이라고 알고있다. -> 그럼 요청과 응답 객체와 관련이 있겠군!
CSRF( 사이트간 요청 위조 )
,XSS
보안을 통해 올바른 요청이 아니면 차단한다!
Spring Security
-> Servlet Filter Chain
를 통해 인증/인가를 관리하는구나!
Session
,JWT
를 사용하는데 필요한 설정을 완전히 분리할 수 있는 환경을 제공한다.
- 우리가 URL 요청이 들어왔을 때 이러한
Http
객체가 Filter
를 타고오는데, Controller
까지 들어오는데 인증/인가를 처리한다.
UserNamePasswordAuthentificationFilter
-> UserName,password
확인해서 인증해주는 것
- 인증되지 않은 사용자가 들어오면 로그인 페이지를 반환한다 ( Exception )
SecurityContextHolder(중요)
-> Spring Securtity
로 인증을 걸친 사용자의 정보를 담고 있는 것! (Authentication
객체를 가지고 있다 / 인증된 객체 가져오기 )
SercurityContextHolder
에 Authentication
객체 담아주는 것 기억하기!
Authentication
: Principle(사용자 식별)
, Credentails(주로 비밀번호)
, Authoities(사용자에게 부여한 권한을 추상화해서 사용)
을 담고 있다.
예제 코드
UserDetailsImpl ( Implements UserDetails )
package com.sparta.springsecurity.security;
import com.sparta.springsecurity.entity.User;
import com.sparta.springsecurity.entity.UserRoleEnum;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
public class UserDetailsImpl implements UserDetails {
private final User user;
private final String username;
private final String password;
public UserDetailsImpl(User user, String username, String password) {
this.user = user;
this.username = username;
this.password = password;
}
public User getUser() {
return user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoleEnum role = user.getRole();
String authority = role.getAuthority();
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
UserDetailsServiceImpl ( Implements UserDetailsService )
xpackage com.sparta.springsecurity.security;
import com.sparta.springsecurity.entity.User;
import com.sparta.springsecurity.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("UserDetailsServiceImpl.loadUserByUsername : " + username);
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));
return new UserDetailsImpl(user, user.getUsername(), user.getPassword());
}
}
- 현재까지의 큰 흐름은 UserDetailsService를 Implements한 class에서 인증된 유저 객체와 유저의 이름, 비밀번호를
UserDetailsImpl
객체에 담아서 반환해준다는 점이다.
2. Annotation
Bean
- 애플리케이션에서 객체를 빈으로 미리 생성해놓고 돌려쓰는 것
-> 스프링이 빈을 관리, 대규모 트래픽을 관리하기 위함
Component
- 개발자가 직접 작성한 Class를 Bean으로 등록하는 것
-> @Component -> @Controller -> Service, @Repsoitory
Bean VS Component
- @Component는 개발자가 지금 개발중인 직접 컨트롤이 가능한 클래스들의 경우 Bean으로 등록하기 위해 사용된다.
- @Bean의 경우 개발자가 컨트롤이 불가능한 외부 라이브러리들을 Bean으로 등록하고 싶은 경우 사용된다.
- '라이브러리에는 @Component 를 붙이지 못하기 때문에 객체를 만들어서 @Bean을 붙여준다.
- // ( 사람이 보는 주석 ) , @( 컴파일러가 보는 주석 )
DI/Ioc
Ioc
: 우리는 구현체 클레스를 직접 관리하지 않고 Config딴에서 제어하고 관리한다.
- 일반적인 제어의 흐름: 사용자가 자신이 필요한 객체를 생성해서 사용
- 역전된 제어의 흐름 : 사용자 자신이 필요한 객체에 @로 표시해주면 컨테이너에서 바로 꺼내주니까 사용한다..
커스텀 Annotation
- @Target: 어디서 쓸지, 클레스, 함수, 파라미터 등..
- @Retention : 유지기간 , 컴파일 코드 , 런타임 ...
Controller의 일반적 실행 흐름
- Client -> Request -> DispaterServlet -> HandlerMapping -> Controller -> View -> DispatcherServlet -> Response -> Client