작업 내용을 기록하고자 한다.
1) build.gradle 설정
ext {
springSecurityVersion = '6.1.9'
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-security"
}
1.5) Role, UserState 클래스 작성 (Enum)
User 테이블을 만들 때 권한과 상태를 까먹어서 급하게 만들었다,,
2) Spring Security 설정 클래스 작성
(import문 생략)
package luckyvicky.petharmony.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.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final UserDetailsService userDetailsService;
public SecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize -> authorize
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.permitAll()
)
.exceptionHandling(exception -> exception.accessDeniedPage("/login"));
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
이 코드에 대해서 설명하자면
@Configuration
@EnableWebSecurity
이 클래스가 Spring Security 설정을 담당하는 구성 클래스임을 나타낸다.
http.authorizeRequests()
요청 URL 권한 설정을 구성한다.
/admin/** 경로에 대해서는 "ADMIN" 권한이 필요하다.
그 외 모든 요청은 인증이 필요하다.
http.formLogin()
폼 기반 로그인 설정을 구성한다.
로그인 URL를 /login으로 지정한다.
로그인 페이지 접근을 모든 사용자에게 허용한다.
http.logout()
로그아웃 설정을 구성한다.
로그아웃 URL을 /logout으로 지정한다.
로그아웃 기능을 모든 사용자에게 허용한다.
http.exceptionHandling()
예외 처리 설정을 구성한다.
접근 거부 시 이동할 페이지를 /login으로 지정한다.
http.build()
구성한 설정을 기반으로 SecurityFilterChain 빈을 생성한다
PasswordEncoder
비밀번호 암호화를 위해 BCryptPasswordEncoder를 사용하도록 설정되어 있다.
요약하면,
이 코드는 Spring Security를 사용하여 ADMIN 권한이 필요한 /admin/** 경로, 폼 기반 로그인 및 로그아웃 기능, 그리고 비밀번호 암호화 기능을 구현하고 있다. 이를 통해 사용자 인증 및 권한 관리가 가능해진다.
3) CustomUserDetailsService
Spring Security에서 기본적으로 제공하는 UserDetailsService 인터페이스는
username을 사용하여 사용자를 검색하도록 설계되었다.
문제
아래 사진을 보면 알 수 있듯이 우리 프로젝트에서는 Email과 Password로 로그인을 진행하고,
회원가입때 사용자 이름을 받는데 username은 중복될 가능성이 있다.
우리 프로젝트에서는 username 대신 이메일을 사용하여 사용자를 검색하는 것이 더 적절하다.
해결
UserDetailService 구현을 이메일 기반으로 수정하면 된다.
먼저, 그럼 이메일이 고유해야 하기 때문에 엔티티를 수정해야 한다.
User.java
@Column(length = 100, nullable = false, unique = true)
private String email;
username 대신 email을 사용하기 때문에 추가해줘야 한다.
SecurityConfig.java
.formLogin(form -> form
.loginPage("/login")
.usernameParameter("email") // 추가
.permitAll()
)
CustomUserDetailService.java
(import문 생략)
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("찾을 수 없는 이메일: " + email));
return org.springframework.security.core.userdetails.User
.withUsername(user.getEmail())
.password(user.getPassword())
.roles(user.getRole().name())
.build();
}
}
Q. 난 이메일을 이용해서 사용자를 찾는 데 왜 예외처리는 UsernameNotFoundException 일까?
A. 이 예외는 Spring Security에서 사용자 인증이 실패했을 때 던져지는 예외로,
이름이 UsernameNotFoundException이지만 실제로는 사용자를 찾지 못했을 때 발생하는 일반적인 예외로 사용된다.
이제 테스트로 설정이 올바르게 작동하는지 확인하면 된다.
근데 아직 로그인, 로그아웃 코드를 작업하지 않아서 시큐리티는 여기까지 ㅎㅎ
추가해야 할 것
- Remember-Me 기능
- OAuth2
- JWT 인증
다음 포스팅
https://chaereemee.tistory.com/6
Spring Security 기록 (2)
전엔 JWT 인증 방법을 쓰지 않고 UserDetails에 대해서 기록했다.JWT를 추가한 전체 코드를 기록하려고 한다. 1) build.gradle필요한 Spring Security, JWT 관련 의존성을 추가한다.이 단계는 프로젝트의 모든
chaereemee.tistory.com
'팀프로젝트_PetHarmony' 카테고리의 다른 글
🌈 아이디 찾기_SMS API(coolsms) (0) | 2024.08.12 |
---|---|
Spring Security 기록 (2) (0) | 2024.08.11 |
🌈 CORS -> CSRF -> JWT (0) | 2024.08.09 |
🌈 Service 코드 파라미터 어떻게 써야할까? (0) | 2024.08.09 |
🌈 Spring Security - 버전 (0) | 2024.08.09 |