왕초보일지

240110 TIL | 스프링시큐리티 로그인 구현하는 중

다시은 2024. 1. 10. 22:53

시큐리티 + 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)

: https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 

 

🚩 프로젝트에서 스프링 시큐리티를 이용한 목표

  • 회원가입 -> 비밀번호를 암호화하여 저장
  • 저장된 회원 정보로 로그인
  • 로그인한 사용자에게 토큰 발급
  • 토큰의 권한에 따라 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