2024. 11. 21. 18:22ㆍFramework & Library/Spring Security
Spring Security 초기화 작업에 대한 큰 틀을 이해했으니 이번에는 사용자(=개발자)가 정의한 보안 설정을 적용해보자. 강의 수강중 작성한 실습 프로젝트는 여기서 확인할 수 있다.
0. 되짚어 보기
이전 게시글에는 단순하게 "사용자(=개발자)가 정의한 보안 설정이 없다면 기본 보안 설정이 적용된다." 라고 이야기 했지만 정확히는 아래의 2가지 조건을 만족해야 기본 보안 설정이 자동으로 적용된다.
- SecurityFilterChain 클래스와 HttpSecurity 클래스가 ClassPath 에 위치한 경우
- SecurityFilterChain 이 Bean 으로 등록되지 않은 경우
정리하면 (1) 의 경우는 항상 만족한다고 보면된다. Spring Security 프레임워크를 가져다 사용하기 때문에 SecurityFilterChain 과 HttpSecurity 클래스는 ClassPath 에 존재한다. 하지만 지정된 ClassPath 를 변경하거나 둘 중 하나의 클래스를 주석처리 및 삭제하는 경우 해당 조건을 만족 못할 수도 있다. 결국 두 클래스를 따로 개발자가 건들지 않는 이상은 항상 만족하는 거라 이해했다.
(2) 의 경우는 개발자가 직접 정의한 보안 설정(SecurityConfiguration)을 통해 SecurityFilterChain 이 Bean 에 등록된 경우 만족하지 않게 된다. 그러면 기본 보안 설정이 OFF 되고 개발자가 정의한 보안 설정만이 적용되는 것이다. 물론 개발자가 별도의 보안 설정을 정의하지 않았다면 만족하게 된다.
위의 내용은 SpringBootWebSecurityConfiguration.SecurityFilterChainConfiguration 클래스의 defaultSecurityFilterChain() 에 지정된 @ConditionalOnDefaultWebSecurity → @Conditional 에 지정된 DefaultWebSecurityCondition 클래스를 통해 알 수 있었다.
1. SecurityConfiguration 정의
그렇다면 보안 설정은 어떻게 정의하면 될까? 답은 가까이에 있다. 바로 이 때까지 자동으로 사용하였던 SpringBootWebSecurityConfiguration.SecurityFilterChainConfiguration 클래스와 유사하게 직접 보안 설정 클래스를 작성해주면 된다.
@Configuration
@EnableWebSecurity // 정의한 보안 설정 클래스를 Spring Security 에서 사용할 때 지정하는 어노테이션
public class SecurityConfiguration {
@Bean
public SecurityFilterChain createSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.build();
}
}
많은 것을 설정하지 않았다. 먼저 해당 설정 클래스에 @Configuration 은 물론 @EnableWebSecurity 도 지정해주었다. @EnableWebSecurity 에 대한 설명은 아래와 같다.
Add this annotation to an @Configuration class to have the Spring Security configuration defined in any WebSecurityConfigurer or more likely by exposing a SecurityFilterChain bean.
WebSecurityConfigurer 에 Spring Security 구성을 정의하거나 Security Filter Chain - Bean 을 노출하여 정의하려면 @Configuration 이 지정된 클래스에 해당 주석을 추가하세요.
확실하지는 않지만 정의한 보안 설정을 Bean 으로 등록해 Spring Security 에서 사용하기 위해 @EnableWebSecurity 를 사용하라는 내용으로 이해하였다.
그리고 HttpSecurity 에 보안 설정을 추가하는 것은 이후의 강의에서 더 자세히 다룰 것이기에 기본적으로 모든 요청에 대해 인증 절차를 거쳐야 한다는 설정과 기본 로그인 방식을 사용한다는 설정을 추가하였다.
이후 디버깅을 통해 defaultSecurityFilterChain() 이 아닌 createSecurityFilterChain() 에 지정한 브레이크 포인트가 걸리는 것을 확인했다. 앞서 말한대로 정의한 보안 설정이 있기 때문에 기본 보안 설정이 수행(적용)되지 않은 것이다.
2. 사용자 설정
또 한 번 되짚어 보자면 현재 Spring Security 에 사용되는 하나의 계정을 자동적으로 생성해주고 있다. 이 작업을 직접하기 위해서는 어떤 방법이 있을까?
2-1. application.yml 사용
먼저 application.yml(또는 properties) 에 사용할 계정을 작성하는 방법이 있다.
spring:
security:
user:
name: user
password: "!testPW24"
roles: USER
설정후 애플리케이션을 실행하니 실행창이 좀 달라졌다. 분명 이전에는 자동으로 생성된 계정에 대한 패스워드(UUID)가 실행창에 출력되었는데 이번에는 출력되지 않았다. 이로인해 계정을 자동으로 생성하는 것도 보안설정과 마찬가지로 설정한 사용자 정보가 있다면 자동으로 생성하지 않는 다는 것을 확인할 수 있었다.
application.yml 에 작성한 사용자 정보로 로그인을 시도하니 인증을 통과해 API 요청("/") 이 수행되어 웹 브라우저에 "home" 이 출력되는 것을 확인할 수 있었다. 참고로 "home" 이 출력되는 것은 이전에 보안 절차를 통과해 수행될 요청에 해당 문자열이 출력되도록 Controller 를 임시로 만들어 두었기 때문이다.
2-2. 설정 클래스 사용
두 번째로는 설정 클래스(@Configuration 지정 클래스)에 직접 정의하는 방법이 있다.
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
...
@Bean
public UserDetailsService userDetailsService() {
UserDetails user1 = User.withUsername("user")
.password("{noop}1111")
.roles("USER")
.build();
UserDetails user2 = User.withUsername("user2")
.password("{noop}2222")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user1, user2);
}
}
물론 해당 방식도 사용자를 설정했기에 자동으로 계정을 생성하지 않아 실행창에 생성된 계정의 패스워드가 출력되지 않는다. 여기서 특이사항은 잘 보면 'user' 변수의 Username 이 application 에 설정한 사용자 계정과 동일한데 실행 후 로그인을 시도하면 설정 클래스에 설정한 사용자의 정보는 로그인을 통과하지만 application.yml 에 설정한 사용자 정보는 통과하지 못한다. 그 이유는 우선순위가 설정 클래스에 지정한 사용자 정보가 application.yml 에 지정한 사용자 정보보다 높기 때문이다(참고로 현재 application.yml 에 지정한 사용자 정보는 주석처리가 되어있지 않다 = 함께 사용 중이다).
3. 정리
이렇게 보안 설정을 정의하는 방식과 사용자(계정)를 설정하는 방식에 대해 알아보았다. 하지만 보안 설정 정의의 경우 거의 필수적으로 활용하겠지만 사용자를 설정하는 것은 당장에 사용하지 않을 것 같다. 그 이유는 앞으로 반필수 적으로 DB 를 사용하게 될테고, 그러면 사용자 정보를 DB 에 저장할 것이기 때문이다.
그러니 "아 이런 방식으로 사용자(계정) 정보를 추가할 수 있구나!" 정도로만 이해하고 이후에 DB 를 통한 사용자 인증/인가 방식에 대해 더 집중해 학습해볼 생각이다.
참고 강의/문서
'Framework & Library > Spring Security' 카테고리의 다른 글
[Spring Security] DelegatingFilterProxy 와 FilterChainProxy (0) | 2024.11.20 |
---|---|
[Spring Security] HttpSecurity 와 WebSecurity (0) | 2024.11.19 |
[Spring Security] SecurityBuilder 와 SecurityConfigurer (0) | 2024.11.19 |
[Spring Security] 의존성 추가 및 기본 설정 적용 (0) | 2024.11.19 |