스프링부트3 회원가입 로그인, 로그아웃 구현하기 - 로그인, 로그아웃 서비스 메서드 작성하기
본문 바로가기

웹/Spring

스프링부트3 회원가입 로그인, 로그아웃 구현하기 - 로그인, 로그아웃 서비스 메서드 작성하기

728x90
반응형

안녕하세요

놀이방 사장입니다.

 

이번 포스팅 회원가입 로그인, 로그아웃 구현 

서비스 메서드를 작성해보겠습니다.

 

1. 저번 포스팅에 이어 엔티티와 리포지터리가 완성되었으니 스프링 시큐리티에서 로그인을 진행할 때 사용자 정보를 가져오는 코드를 작성하겠습니다.

 

service디렉터리에 UserDetailService.java 만들어 작성한다.

package me.joyeonggyu.springbootdeveloper.service;

import lombok.RequiredArgsConstructor;
import me.joyeonggyu.springbootdeveloper.domain.User;
import me.joyeonggyu.springbootdeveloper.repository.UserRepository;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service

// 스프링 시큐리티에서 사용자 정보를 가져오는 인터페이스
public class UserDetailService implements UserDetailsService {
    private final UserRepository userRepository;

// 사용자 이름(email)로 사용자의 정보를 가져오는 메서드
    @Override
    public User loadUserByUsername(String email){
        return userRepository.findByEmail(email)
                .orElseThrow(() -> new IllegalArgumentException((email)));
    }
}


 

 

 

스프링 시큐리티에서 사용자의 정보를 가져오는 UserDetailsService인터페이스 구현 필수로 구현해야하는 loadUserByUsername() 메서드를 오버라이딩해서 사용자 정보를 가져오는 로직 작성

 

2. 시큐리티 설정하기

인증을 위한 도메인과 리포지터리 , 서비스가 완성되었으니 실제 인증을 처리하는 시큐리티 설정파일 WebSecurityConfig.java파일 작성

같은 패키지내에 config패키지 새로 생성

package me.joyeonggyu.springbootdeveloper.config;

import lombok.RequiredArgsConstructor;
import me.joyeonggyu.springbootdeveloper.service.UserDetailService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;

@RequiredArgsConstructor
@Configuration

public class WebSecurityConfig {
    private final UserDetailService userService;

    //스핑 시큐리티 기능 비활성화
    @Bean
    public WebSecurityCustomizer configure(){
        return (web) -> web.ignoring()
                .requestMatchers(toH2Console())
                .requestMatchers(new AntPathRequestMatcher("/static/**"));
    }

    //특정 HTTP 요청에 대한 웹 기반 보안 구성
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        return http
                .authorizeRequests()    //인증 ,인가 설정
                .requestMatchers(new AntPathRequestMatcher("/login"),
                                 new AntPathRequestMatcher("/signup"),
                                 new AntPathRequestMatcher("/user")).permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()    //폼기반 로그인 설정
                .loginPage("/login")
                .defaultSuccessUrl("/articles")
                .and()
                .logout()
                .logoutSuccessUrl("/login")
                .invalidateHttpSession(true)
                .and()
                .csrf().disable()      //csrf 비활성화
                .build();
    }

    //인증 관리자 관련 설정
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http,
                                                       BCryptPasswordEncoder bCryptPasswordEncoder,
                                                       UserDetailService userDetailService) throws Exception{
        return http.getSharedObject(AuthenticationManagerBuilder.class)
                .userDetailsService(userService)    //사용자 정보 서비스 설정
                .passwordEncoder(bCryptPasswordEncoder)
                .and()
                .build();
    }

    //패스워드 인코더로 사용할 빈 등록
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

 

 

 

뭐지 왜 다 주석으로 나오지...

일단 책에서는 

.requestMatchers("/static/**");

이렇게 경로를 지정하는데 저는 이게 오류가 나더라구요

그래서 chatGpt에게 물어보니깐 

.requestMatchers(new AntPathRequestMatcher("/static/**"));

이렇게 쓰면 된다라고 하더라구요 이렇게 쓰니깐 오류가 안 나더라구요

 

일단 잘못된 인수가 넘어가져서 오류가 뜨는 거 같네요.. 흠

 

지피티 설명에 따르면

requestMatchers() 메서드는 RequestMatcher인스턴스나 AntPathRequestMatcher를 인수로 받는 거 같고

일반적으로 패턴 문자열을 이용해 URL을 매칭한다고 합니다.

 

requestMatchers() 메서드를 호출할 떄는 인수로 문자열을 전달하는 게 아니라 RequestMatcher 인스턴스를 전달해야한다.

 

일단requestMathchers()에 대한 설명은 여기까지 하고 위에 코드 설명을 하자면

@Bean
public WebSecurityCustomizer configure(){
    return (web) -> web.ignoring()
            .requestMatchers(toH2Console())
            .requestMatchers(new AntPathRequestMatcher("/static/**"));
}

이 부분은 스프링 시큐리티의 모든 기능을 사용하지 않게 설정하는 코드입니다.

즉 인증, 인가 서비스를 모든 곳에 적용하지 않습니다.

일반적으로 정적리소스에 설정 (이미지 , HTML) 

정적 리소스만 스프링 시큐리티 사용을 비활성화 하는데 static 하위 경로에 있는 리소스와 h2 데이터를 확인하는데 사용하는 h2-console 하위 url을 대상으로  ignoring메서드를 사용

 

 

public SecurityFilterChain filterChain(HttpSecurity http)

이 부분은 특정 HTTP 요청에 대해 웹 기반 보안을 구성

 

이 메서드에서 인증, 인가 및 로그인, 로그아웃 관련 설정을 할 수 있다.

 

.authorizeRequests()    //인증 ,인가 설정

특정경로에 대한 엑세스 설정

각 설정들

requestMatchers

특정 요청과 일치하는 ur에 대한 액세스를 설정

permitAll

누구나 접근이 가능하게 설정 

여기서는 /login, /signup, /user 로 요청이 오면 인증/인가 없이도 접근 할 수 있다.

anyRequest

위에서 설정한 url이외의 요청에 대해서 설정

authenticated

별도의 인가는 필요하지 않지만 인증이 성공된 상태여야 접근할 수 있다.

.formLogin()

폼 기반 로그인 설정을 한다.

각 설정들

loginPage

로그인 페이지 경로 설정

defaultSuccessUrl

로그인이 완료되었을 떄 이동할 경로 설정

.logout()

로그 아웃 관련 설정들

logoutSuccessUrl

로그아웃 완료시 이동할 경로

invalidateHttpSession

로그아웃 이후에 세션을 전체 삭제할지 여부를 설정

.csrf().disable() 

CSRF설정 비활성 CSRF공격을 방지하기 위해서는 활성화하는게 좋으나 실습을 편리하게 하기 위해 비활성화

public AuthenticationManager authenticationManager

인증 관리자 관련 설정, 사용자 정보를 가져올 서비스를 재정의하거나 인증방법(LDAP, JDBC)기반인증을 설정 하 ㄹ때 사용

 

.userDetailsService(userService) 

사용자 서비스 설정

userDetailsService

사용자 정보를 가져올 서비스를 설정, 이 때 설정하는 서비스클래스는 UserDetailsService를 상속받은 클래스여야 한다,.

passwordEncoder

비밀번호를 암호화하기 위한 인코더를 설정

public BCryptPasswordEncoder bCryptPasswordEncoder(){
    return new BCryptPasswordEncoder();
}

패스워드 인코더를 빈으로 등록

 

이상으로  스프링부트3 회원가입 로그인, 로그아웃 구현하기 - 로그인, 로그아웃 서비스 메서드 작성하기 포스팅을 마치겠습니다.

반응형