안녕하세요
놀이방 사장입니다.
이번 포스팅 회원가입 로그인, 로그아웃 구현
서비스 메서드를 작성해보겠습니다.
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 회원가입 로그인, 로그아웃 구현하기 - 로그인, 로그아웃 서비스 메서드 작성하기 포스팅을 마치겠습니다.
'웹 > Spring' 카테고리의 다른 글
스프링 JWT 서비스 구현하기 (0) | 2023.11.19 |
---|---|
JWT, 토큰 기반 인증이란? (1) | 2023.11.18 |
스프링부트3 회원가입 로그인, 로그아웃 구현하기 - 회원 도메인 만들기 (0) | 2023.10.23 |
스프링부트3 회원가입 로그인, 로그아웃 구현하기 - 사전지식 스프링 시큐리티 (0) | 2023.10.23 |
스프링부트3 블로그 글 삭제 기능 추가하기 (0) | 2023.10.22 |