프론트 부분의 구조나 디자인에 대한 내용은 각자 원하시는대로 하시면 될 것 같고,
저는 디자인은 GPT, V0와 같은 AI 툴들을 사용해서 만들었습니다. (디자인은 자신이..😅)
UI가 필요하신 분들은 [로그인 기능 구현] 여기 깃 코드 사용하시면 될 것 같습니다.
Spring Security 공부를 위해 로그인 기능을 구현하는 것이기에 프론트보다는 백엔드에 초점을 맞추어 작성 하도록 하겠습니다.
프로젝트 세팅을 하지 않으신 분들은 [React+SpringBoot 프로젝트 생성하기] 블로그를 먼저 보고 와주시길 바랍니다.
Security를 사용하기 전에 간략하게 무엇인지를 알아보자면
Spring Security
는 Spring 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크이다.
Spring Security
는 '인증'과 '권한'에 대한 부분을 Filter 흐름에 따라 처리하고 있다. Filter는 Dispatcher Servlet
으로 가기 전에 적용되므로 가장 먼저 URL 요청을 받는다.
Spring Security
는 보안과 관련해서 체계적으로 많은 옵션을 제공해주기 때문에 개발자 입장에서는 일일이 보안관련 로직을 작성하지 않아도 된다는 장점이 있다.
스프링은 버전에 따라 구현 방식이 조금씩 변경되는데 시큐리티의 경우 특히 세부 버전별로 구현 방법이 많이 다르기 때문에 버전마다 구현 특징을 확인해야 한다고 합니다.
[참고], [Spring Security GitHub Releases Note]
Security를 사용하기 위해서는 build.gradle
파일에 의존성을 먼저 추가하여야 합니다.
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-security' // Spring Security
...
}
의존성을 추가하면 Spring Security를 사용할 수 있습니다.
Security를 사용하기 위한 SecurityConfig
클래스를 생성합니다.
사용하는 메서드명(ex: filterChain
)은 원하시는 이름으로 정하고
리턴 타입은 SecurityFilterChain
으로 하셔야 합니다.
@Configuration
@EnableWebSecurity
WebSecurityConfigurerAdapter
클래스를 상속받아 사용합니다./* 과거에는 이렇게 구현하였지만 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
/*
Spring Boot 3.0 이상
Spring Security 6 이상에서는 WebSecurityConfigurerAdapter는 사용 불가 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
...
}
Spring Security
의 HTTP 보안 설정을 구성하기 위한 클래스입니다.WebSecurityConfigurerAdapter
를 확장하여 사용하며, configure(HttpSecurity http)
메소드를 오버라이드하여 필요한 정보를 추가합니다.http
에서 사용하는 메서드들은 람다 형태로 사용하시면 됩니다.@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 인가
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/", "/login").permitAll()
.requestMatchers("/getUserInfo").hasRole("ADMIN")
.anyRequest().authenticated()
);
// 인증
http
.formLogin((auth) -> auth.loginPage("/login") // 권한이 없는 admin과 같은 경로로 사용자가 요청했을 때 오류 페이지가 아닌 작성한 "경로"로 Spring Security가 리다이랙트 시켜줌
.loginProcessingUrl("/loginProc") // 해당 경로로 요청이 들어오면 Security가 로그인 처리를 진행
.defaultSuccessUrl("/login", true)
.permitAll() // 로그인 처리를 한다는게 permitAll() 권한을 준다는 것 같음
);
http
.csrf((auth) -> auth.disable()); // POST방식으로 요청을 진행할 때 CSRF(사이트 위변조 방지 설정) 토큰을 보내야 로그인 처리를 가능하게 함, 이러한 설정은 Spring Security에서 설정되어 있음
// 개발환경에서는 토큰을 사용하는 것이 불편하므로 disable 처리, 추후에 inable 처리하도록 수정
return http.build();
}
}
requestMatchers(경로)
: "경로"에 대한 권한을 설정할 수 있다.permitAll()
: 모든 사용자에게 접근 가능하도록 설정hasRole(권한)
: "권한"이 있는 사용자만이 requestMatchers(경로)에 설정된 경로에 접근할 수 있다.hasAnyRole(권한1, 권한2, ...)
: 여러 "권한"에 대해 접근을 제어할 수 있다.anyRequest()
: 위에서 처리하지 못한 나머지 경로에 대한 권한 제어를 처리할 수 있음.authenticated()
: 로그인한 사용자만이 접근할 수 있도록denyAll()
: 모든 사용자의 접근을 제한함requestMatchers()
를 이용해 경로에 대한 접근을 제한할 때 순서가 중요하다. 많은 권한에 대한 제한은 가장 마지막에 작성하는 것이 올바르다.
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/", "/login").permitAll()
.requestMatchers("/getUserInfo").hasRole("ADMIN")
.anyRequest().authenticated()
);
"/"
, "login"
경로일 경우 permitAll()
(=모든 사용자가 접근이 가능하도록) 처리"/getUserInfo"
경로일 경우 "ADMIN" 권한을 가진 사용자만 허용해준다.http
.formLogin((auth) -> auth.loginPage("/login")
.loginProcessingUrl("/loginProc")
.defaultSuccessUrl("/login", true)
.permitAll()
);
/login
페이지로 리다이렉트합니다.'/loginProc
요청을 보내면 Spring Security가 해당 요청을 가로채 로그인 처리를 수행Spring Security
가 성공 후 "/login"
경로로 리다이랙트를 시도함이처럼 Spring Security
를 이용해 "인증", "인가"에 대한 처리를 할 수 있습니다.
저는 [개발자 유미 유튜브] 를 참고하여 Spring Security
공부를 진행하고 있습니다.
영상에서는 SpringBoot 프로젝트만을 이용해서 알려주시기 때문에 제 코드와는 다른 부분이 있을 수 있습니다.
추가적인 이해나 설명이 더 필요하신 분들은 유튜브 들어가서 확인해 보시면 좋을 것 같습니다~!