시큐리티 + jwt
https://github.com/Colabear754/authentication_example/tree/master
빨간줄 다 없애고 실행시키니 로그에 뜬 오류
java.lang.Class otFoundExcption:javax.xml.bind.JAXBException
=>
implementation 'javax.xml.bind:jaxb-api:2.3.0'
secret-key 설정 (jwt.yml)
🚩 프로젝트에서 스프링 시큐리티를 이용한 목표
- 회원가입 -> 비밀번호를 암호화하여 저장
- 저장된 회원 정보로 로그인
- 로그인한 사용자에게 토큰 발급
- 토큰의 권한에 따라 API 접근 권한 제어
- 로그인 하지 않은 사용자는 게시글 조회만 가능
- 로그인 된 사용자의 정보를 토대로 CUD 기능 동작
회원가입, 로그인 구현
패키지 보면서 다시 복기하기
SecurityConfig
:스프링 시큐리티 기본 설정
TokenProvider
:토큰 생성
Signcontroller
: signUp login 컨트롤러
SignInRequest/Response
: 로그인시 이메일, 비밀번호 입력받음
SignUpRequest/Response
: 회원가입시 이메일, 비밀번호, 이름 입력받음
SignService
회원가입 -request의 이메일로 이미 사용중인 이메일인지 검사하고 비밀번호를 인코딩해서 DB에 저장한다.
로그인 - request의 이메일에 해당하는 비밀번호와 request로 받은 비밀번호를 검사한다. 일치하면 토큰을 발급한다.
❗ SecurityConfig
@Configuration
class SecurityConfig {
private val allowedUrls = arrayOf("/", "/swagger-ui/**", "/v3/**", "/sign-up", "/sign-in")
@Bean
fun filterChain(http: HttpSecurity) = http
.csrf { obj: CsrfConfigurer<HttpSecurity> -> obj.disable() } // 공격 방지위해서는 활성화해야 함
.authorizeHttpRequests {
it.requestMatchers(*allowedUrls).permitAll() // requestMatchers의 인자로 전달된 url을 모두에게 허용
.anyRequest().authenticated() // 그 외의 모든 요청은 인증 필요
}
.sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) } // 세션을 사용하지 않으므로 STATELESS 설정
.build()!!
// 패스워드 인코더 등록
@Bean
fun bCryptPasswordEncoder(): BCryptPasswordEncoder =
BCryptPasswordEncoder() // 해시 함수를 사용하여 패스워드를 저장하고 검증하는데 사용되는 PaswordEncoder 의 구현체
}
"/" : 애플리케이션의 홈 또는 랜딩 페이지
"/swagger-ui/**" : swagger ui 인터페이스에 접근 가능
"/v3/**" : api 버전 3과 관련된 리소스 또는 엔드포인트에 대한 접근 허용 ?? 잘 모르겠다.
v3을 빼고 실행시켰을 때 swagger load 가 불가능하다고 떴었다.
BcryptPasswordEncoder : PasswordEncoder 를 구현한 클래스이다.
스프링 시큐리티에서 기본으로 제공하는 암호화 모듈이다.
변경되어야 할 것 : 모두에게 허용되는 목록에 게시물과 댓글 조회가 추가되어야 한다.
그 외 작성, 수정, 삭제 등은 로그인 된 사용자에게만 허용 => 토큰으로 검증
허용되지 않은 자가 시도하면 403 오류가 뜨던데 다른 메시지를 줄 수도 있을까??
❗ jwt.yml
비밀키, 토큰유효시간, 발급자 를 설정해놓는다.
❗ SignService
@Service
class SignService(
private val userRepository: UserRepository,
private val tokenProvider: TokenProvider,
private val encoder: PasswordEncoder
) {
@Transactional
fun registerMember(request: SignUpRequest): SignUpResponse {
val isExistAccount = userRepository.existsByEmail(request.email)
if (isExistAccount) throw IllegalArgumentException("이미 사용중인 아이디입니다.")
return SignUpResponse.toSignUpResponse(userRepository.save(User.toUser(request, encoder)))
}
@Transactional
fun signin(request: SignInRequest): SignInResponse {
val user = userRepository.findByEmail(request.email).takeIf { encoder.matches(request.password, it.userPassword) }
?: throw IllegalArgumentException("아이디 또는 비밀번호가 일치하지 않습니다.")
val token = tokenProvider.createToken("${user.id}")
return SignInResponse(user.name, token)
}
}
생성자로 UserRepository, TokenProvider, PasswordEncoder 를 주입받는다.
회원가입
: request 로 받은 이메일이 중복되는지 확인하고 없으면 encoder 를 통해 비밀번호를 암호화해서 DB 에 저장한다.
로그인
: request 로 받은 이메일을 repsitory에서 찾고 그 비밀번호와 request의 비밀번호를 검사한다.
일치하면 tokenprovider 로 token을 생성해서 받는다.
encoder.matches 비밀번호 비교
암호화되지 않은 비밀번호와 암호화되어서 저장되어있는 비밀번호를 알아서 검사해준다.
해야할 것
- api 명세 수정
- 토큰의 권한에 따라 API 접근 권한 제어
- 로그인 하지 않은 사용자는 게시글 조회만 가능
- 로그인 된 사용자의 정보를 토대로 CUD 기능 동작
- takeIf
- 아이디 UUID
'왕초보일지' 카테고리의 다른 글
240112 TIL | Co-Ha 내가 구현한 기능 공부, 기록 (1) | 2024.01.12 |
---|---|
240111 TIL | (3) | 2024.01.11 |
240109 TIL | (2) | 2024.01.09 |
240108 TIL | 7주차 팀프로젝트 (3) | 2024.01.08 |
240105 TIL | Todo과제 (1) | 2024.01.05 |