Spring Security_로그인 기능 구현/Spring Security Basic

로그인 기능_Spring Security 기본편(11)

김쟈워니 2024. 11. 4. 15:19

로그인 기능_Spring Security 기본편(10)에서 배운 것

CSRF 보호 설정시 GET 방식 로그아웃 설정 방법

Spring Security에서는 기본적으로 CSRF 보호 설정이 활성화 된 경우 POST 방식 로그아웃을 권장

요구에 따라 GET 방식 로그아웃

 

1. Security Config 클래스 로그아웃설정

http.logout()메서드를 사용하여 로그아웃 URL 과 성공후 이동할 URL 설정

http.logout((auth)->auth.logoutUrl("/logout").logoutSuccessUrl("/"));

 

2. GET방식 로그아웃 처리를 위한 LogoutController 생성

SecurityContextLogoutHandler 를 통해 수동으로 로그아웃 처리


InMemory 방식 유저 정보 저장

InMemory 저장 방식 두가지

DB를 InMemory로 활용하는 방식

DB 없이 소수의 유저를 자동으로 저장하는 방식

 

토이 프로젝트 또는 시큐리티 로그인 환경은 필요하지만 소수의 회원 정보만 가지며 데이터베이스라는 자원을 투자하기 힘든 경우 회원가입 없는 InMemory 방식으로 유저 저장

 

InMemory 인증 관련 공식 문서

 

In-Memory Authentication :: Spring Security

In the following sample, we use User.withDefaultPasswordEncoder to ensure that the password stored in memory is protected. However, it does not protect against obtaining the password by decompiling the source code. For this reason, User.withDefaultPassword

docs.spring.io

 

InMemoryUserDetailsManager 클래스를 통해 유저를 등록

 

InMemory방식 프로젝트 과정

사전 준비( 앞에 단계는 동일하기 때문에 순서대로 간단 요약)

프로젝트 생성

  • SpringSecurity, Spring Web, Spring Boot DevTools 의존성 추가
  • JSP 및 JSTL 문법 사용을 위한 의존성 추가

JSP 및 JSTL 관련 의존성

<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>
		<dependency>
			<groupId>jakarta.servlet.jsp.jstl</groupId>
			<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
		</dependency>
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>jakarta.servlet.jsp.jstl</artifactId>
		</dependency>
  • Spring Boot 3.x버전이나 Jakarta EE 9 이상으로는 위에 의존성을 추가함 

application.properties 설정

  • 서버 포트 설정
  • JSP 설정
spring.application.name=SpringSecurityBasicInMemory

server.port=9091

spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp

 

JSP 이용을 위해 application.properties에서 prefix 설정을 맞추기 위해 src/main/webapp/WEB-INF/views 폴더 생성 

해당 폴더 내부에 루트 페이지에 사용할 .jsp 파일 만들기


InMemory방식 프로젝트
SecurityConfig 파일 내부에 UserDetailsService 클래스를 이용하여 Bean을 등록하여 회원을 생성

 

SecurityConfig.java

package com.jw.SpringSecurityBasicInMemory.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	// 시큐리티 config
	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		http.authorizeHttpRequests((auth)->auth
				.requestMatchers("/","/login","/loginProc","/WEB-INF/**").permitAll()
				.anyRequest().authenticated()
				);
		//로그인 페이지
		http
		.formLogin((auth)-> auth
				.loginPage("/login")
				.loginProcessingUrl("/loginProc")
				.defaultSuccessUrl("/")
				.permitAll()
				);
		
		http.
		logout((auth)->auth
				.logoutUrl("/logout")
				.logoutSuccessUrl("/")
				);
		
		http.csrf((auth)->auth.disable());
		
		return http.build();				
	}

	@Bean
	BCryptPasswordEncoder bCryptPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	//
	@Bean
	UserDetailsService userDetailsService(BCryptPasswordEncoder bCryptPasswordEncoder) {
	    UserDetails user1 = User.builder()
	        .username("user1")
	        .password(bCryptPasswordEncoder.encode("1234"))
	        .roles("ADMIN")
	        .build();

	    UserDetails user2 = User.builder()
	        .username("user2")
	        .password(bCryptPasswordEncoder.encode("1234"))
	        .roles("USER")
	        .build();

	    return new InMemoryUserDetailsManager(user1, user2);
	}

}

@Bean SecurityFilterChain filterChain(HttpSecurity http): HTTP 보안 설정을 담당하며, 각 요청에 대해 어떤 보안 규칙이 적용될지를 정의

@Bean BCryptPasswordEncoder bCryptPasswordEncoder():

BCrypt 암호화기: 사용자 비밀번호를 안전하게 암호화하기 위해 BCryptPasswordEncoder를 사용하여 암호화

@Bean UserDetailsService userDetailsService(BCryptPasswordEncoder bCryptPasswordEncoder):

InMemoryUserDetailsManager: Spring Security에서 사용자 정보를 메모리에 저장하는 방식으로, 실제 DB가 아닌 메모리에 사용자 정보를 유지