[Spring Security 6.x] Default Authentication(기본 인증 설정, 기본 로그인 페이지)
Spring Security에 대한 의존성을 추가하고 Spring Boot를 실행하여 8080포트에 예상과는 다른 화면을 볼 수 있다.
해당 포스트에서는 Spring Security의 초기화 및 기본 설정에 대한 원리에 대한 내용을 다룬다.
기본 로그인 페이지 해결 방법을 위해 방문한 것이라면 해결 방법은 다음과 같다.
- Username : user
- Password : 콘솔창에서 "Using generated Security password : " 이후 등장한 문자열
목차
- Spring Security의 기본 설정
- Spring Security 소스 기반 작동 원리
1. Spring Security 기본 설정
가장 기본이 되는 Index Controller를 생성해주었다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexController {
@GetMapping("/")
public String index(){
return "index";
}
}
실행 결과는 다음과 같다. 주소창의 url 역시 localhost:8080/이 아니라 localhost:8080/login으로 이동한 것을 볼 수 있다.
별도의 login.html, login.jsp 등의 파일을 생성하지 않았어도 localhost:8080에 대한 모든 요청은 이 페이지에서
인증 여부를 검사받아야 접근이 가능하도록 바뀐 것이다.
이러한 동작을 하는 원인은, Spring Security에 대한 의존성을 추가하였을 때 Security의 초기화 작업 및 보안 설정이 이루어지기 때문이다.
즉, 사용자가 별도의 보안 설정을 하지 않았더라도 Security가 기본적인 웹 보안 기능을 현재 시스템에 적용시켜 작동한다.
초기화가 진행된 기본 설정은 다음과 같다.
Spring Security의 기본 보안 기능
- 기본 설정은 모든 url 요청에 대해 인증 여부를 검사하고, 인증이 승인되어야 url 자원에 접근이 가능하다.
- 인증 방식은 기본으로 Form 로그인 방식과 HttpBasic 로그인 방식을 제공한다.
- 인증을 시도할 수 있는 로그인 페이지가 별도로 자동 생성되어 제공된다.
- 인증 승인이 이루어 질 수 있도록 한 개의 계정이 기본적으로 제공된다.
하지만 이 방식은 말 그대로 Spring Security가 제공해주는 아주 기본적인 기능일 뿐 이것을 사용한다고 보안 문제가
해결되는 것은 아니다.
접근하는 사용자에 대한 계정이 1개만 있을 수는 없을 뿐더러, 사용자의 역할 구분(인가 처리) 역시 여러 개가 존재 할 수 있기 때문이다.
2. Spring Security 소스 기반 작동 원리
2-1 User 계정 자동 생성의 원리
기본 인증 기능을 통해 저 Login Page에 대한 인가 처리를 받을 수 있는 계정은 다음과 같다.
- Username : user
- Password : UUID로 생성된 랜덤 문자열
user라는 아이디는 고정되어있으나 Password는 랜덤 문자열이기 때문에 사용자는 알 방법이 없을 것 같지만, Spring Boot가 동작할 때 Console창에 해당 Password가 출력되어 확인이 가능하다.
"Using generated Security password : " 이후 적힌 랜덤 문자열이 UUID로 생성된 문자열이며 이를통해 인가 받을 수 있다.
사용자에게 "user"라는 Username과 UUID를 통한 랜덤문자열의 "password"를 제공하는 원리는 다음과 같다.
앞서 Spring Security는 Spring Boot가 실행될 때 자동 설정에 의해 내부적으로 웹 보안 기능이 작동하기 시작한다.
이를 통해 Bean 등록 및 설정을 진행하는데 SecurityProperties라는 클래스에서 기본 계정 하나를 제공하는 클래스라 볼 수 있다.
SecurityProperties 클래스 내부에는 static으로 선언된 User라는 클래스가 따로 존재한다.
이 클래스에서는 기본 보안 설정에 사용될 계정을 생성해주며 내용은 앞서 언급한 아이디, 패스워드를 기반으로 한다.
2-2 Spring Security 기본 보안 작동 원리
SecurityProperties는 기본적인 계정을 설정해주는 모습을 볼 수 있었다. 반면, SpringBootWebSecurityConfiguration이라는 클래스는 Spring Security의 기본 보안에 대한 설정이 적혀있는 클래스라고 볼 수 있다.
해당 클래스의 코드에는 아래와 같은 코드가 존재한다.
코드의 윗 줄 부터 살펴보자면 다음과 같다.
1. @ConditionalOnDefaultWebSecurity 애너테이션
해당 애너테이션을 Control+클릭을 통해 계속 파고 들어가다보면 DefaultWebSecurityCondition이라는 클래스가 나온다.
이 클래스에서는 @ConditionOnMissingBean과 @ConditionalOnClass라는 애너테이션이 존재하는데, 이 두 가지 Condition을 만족해야 기본 Security Condition을 만족한다고 볼 수 있는 것이다.
1-1 @ConditionalOnClass 애너테이션
- "SecurityFilterChain 클래스와 HttpSecurity 클래스가 Class Path에 존재하는가?" 에 대한 참/거짓 여부를 판별한다.
- 현재 Spring Security에 대한 의존성을 추가하였기 때문에 저 두 개의 클래스는 모두 존재하여 조건은 "참"이다.
1-2 @ConditionalOnMissingBean 애너테이션
- "SpringFilterChian 클래스가 Bean으로 생성이 되어있지 않는가?" 에 대한 참/거짓 여부를 판별한다.
- OnMissingBean이기 때문에 Bean으로 생성이 되어있다면 거짓, 생성되어있지 않다면 참이다.
따라서 현재 우리는 별도의 SecurityFilterChain을 Bean으로 등록하지 않았고, Security 의존성을 프로젝트에 추가하였기 때문에 두 가지 조건이 모두 참이라 Security의 기본 보안 기능이 작동한 것이다.
2. authenticated()
@Bean
@Order(2147483642)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> {
((AuthorizeHttpRequestsConfigurer.AuthorizedUrl)requests.anyRequest()).authenticated();
});
http.formLogin(Customizer.withDefaults());
http.httpBasic(Customizer.withDefaults());
return (SecurityFilterChain)http.build();
}
다음은 위의 두 조건을 만족했을 때 기본적으로 Security가 생성하는 SecurityFilterChain Bean이다.
별 다른 내용은 없고 다음과 같은 내용만 확인하면 된다.
- anyRequest() : 어떠한 요청에 대해서라도. 즉, 모든 요청에 대해서
- authenticated() : 인증 진행한다.
즉, Security의 기본 보안은 URL에 어떠한 요청에 대해서라도 인증을 진행한다는 의미가 된다.
이후 기본적으로 제공하는 formLogin 방식과 httpBasic 방식을 제공하는 것을 코드로 확인할 수 있다.