1 ) Spring Security 정의
- Spring 기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크
- 인증(Authentication) 과 권한(Authorization) 에 대한 부분을 Filter의 흐름에 따라 처리를 하고 있다.
2) 인증(Authentication) 과 권한(Authorization)
- 인증
- 사이트에 접속하려고 할 때의 확인 절차
- Session과 Token(Sessionless)을 통한 인증 절차
- SNS 로그인에 인증 위임
- 인가 or 권한
- 사용자의 권한 설정 절차
- 특정 페이지 및 리소스에 접근 가능 판단
- @Secure, @PrePostAuthorize 어노테이션으로 권한 체크
- AOP를 이용하여 권한 체크
* 인증 절차를 거친 후 권한절차를 진행하게 된다.
* 요즘에는 아이디와 패스워드가 아닌 이메일과 패스워드로 많은 인증 절차를 확인하는 추세이다.
3) Spring Security 의존성 추가
dependencies {
implementation "$boot:spring-boot-starter-security" // boot = "org.springframework.boot"
}
- Security 의존성을 추가하면 url에 접속 시 인증 절차를 받게 된다.
- 해당 로그인 화면은 Spring Security에서 제공하는 기본적인 로그인 페이지이다.
4) SecurityContextHolder, SecurityContext, Authentication의 구조
- SecurityContextHolder > SecurityContext > Authentication > (Principal, Credentials, Authorities)
- SecurityContextHolder
- SecurityContext 객체를 보관하는 Wrapper 클래스이고 ThreadLocal의 전략을 설정, 설정에 따라 쓰레드 단위로 SecurityContext 객체를 할당한다.
- SecurityContext
- Authentication 객체를 보관되는 저장소 역할. 필요시 SecurityContext로부터 Authentication 객체를 꺼내서 사용 가능
- 각 스레드마다 할당되는 고유 공간인 ThreadLocal에 저장되므로 동일한 스레드인 경우 필요한 아무 곳에서나 참조 가능
- 서버에 접속해서 각 Thread는 각각의 ThreadLocal에 SecurityContext를 가지고 동시에 HttpSession에도 저장
- Authentication
- Principal : 접근 주체 아이디
- Credentials : 접근 주체 패스워드
- Authrorities : 인증된 접근 주체자의 권한 목록
- @Secured
- 특정 권한만 접근이 가능하다는 것을 나타내는 Annotation
- @PreAuthorize
- 메소드 실행전에 인증을 체크
- @PostAuthorize
- 메소드 실행후에 인증을 체크
- @EnableWebSecurity, @EnableGlobalMethodSecurity
- WebSecurityConfigurerAdapter를 상속받은 클래스에 SpringSecurityFilterChain 동작 및 메소드에 Security 적용
@RestController
public class MainController {
@RequestMapping("/")
public String main(){
return "메인페이지";
}
@RequestMapping("/auth")
public Authentication auth(){
return SecurityContextHolder.getContext().getAuthentication();
}
}
@
Url Login 접속 방법
- Spring Security 의존성 적용 후 기본적으로 별도의 계정을 yml이나 Config에서 지정하지 않으면, user라는 아이디로 해당 Security Password를 통해 url 에 접속 가능 하다.
- yml 적용
- Config를 통한 Role 지정(지정 시 yml의 user는 무시)
spring:
security:
user:
name: user1
password: 1111
roles: USER
@RestController
public class MainController {
...(위의 코드 중략)
@PreAuthorize("hasAnyAuthority('ROLE_USER')")
@RequestMapping("/user")
public SecurityMessage user(){
return SecurityMessage.builder()
.auth(SecurityContextHolder.getContext().getAuthentication())
.message("유저 정보")
.build();
}
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
@RequestMapping("/admin")
public SecurityMessage admin(){
return SecurityMessage.builder()
.auth(SecurityContextHolder.getContext().getAuthentication())
.message("관리자 정보")
.build();
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SecurityMessage {
private Authentication auth;
private String message;
}
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(User.builder()
.username("user2")
.password(passwordEncoder().encode("2222"))
.roles("USER")
).withUser(User.builder()
.username("user3")
.password(passwordEncoder().encode("3333"))
.roles("ADMIN")
);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) ->
requests.antMatchers("/").permitAll()
.anyRequest().authenticated());
http.formLogin();
http.httpBasic();
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
참고
https://wildeveloperetrain.tistory.com/163
'Spring > 1-5. Spring Security' 카테고리의 다른 글
6) DaoAuthenticationManager와 UserDetailsService 사 (0) | 2023.06.11 |
---|---|
5) BasicAuthenticationFilter를 사용하여 토큰 인증 (0) | 2023.06.08 |
4) Form Login과 Logout Filter (0) | 2023.06.04 |
3. Spring Security Authentication 구조와 매커니즘 (0) | 2023.06.04 |
2. Spring Security의 Filter (0) | 2023.06.04 |