본문 바로가기

카테고리 없음

PasswordEncoder, 간단한 jwt, 실행파일, yml

@Configuration
class PasswordEncoderConfig {
    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return BCryptPasswordEncoder()
    }
}

이게 있어야 비밀번호를 안전하게 처리할수 있다.

 

하지만 이것만으론 부족하고, 회원가입을 할때에 페스워드인토더랑 연결이 되야한다.

data class AdminSignUpRequest(
    val email: String,
    val password: String,
    val passwordCheck: String,
    var nickname: String,
    var address: String,
    var phoneNumber: String
) {
    fun toEntity(passwordEncoder: PasswordEncoder): Admin {
        return Admin(
            email = email,
            password = passwordEncoder.encode(password), // 비밀번호 암호화
            nickname = nickname,
            address = address,
            phoneNumber = phoneNumber
        )
    }
}

그러면 이제 제대로 암호화가 된다.

 

그러면 이제 jwt를 만들어야 한다.

@Component
class JwtPlugin(
    @Value("\${auth.jwt.issuer}") private val issuer: String,
    @Value("\${auth.jwt.secret}") private val secret: String,
    @Value("\${auth.jwt.accessTokenExpirationHour}") private val accessTokenExpirationHour: Long,
) {
    fun validateToken(jwt: String): Result<Jws<Claims>> {
        return kotlin.runCatching {
            val key = Keys.hmacShaKeyFor(secret.toByteArray(StandardCharsets.UTF_8))
            Jwts.parser().verifyWith(key).build().parseSignedClaims(jwt)
        }
    }

    fun generateAccessTokenForSocialUser(
        subject: String,
        nickname: String,
        email: String,
        roles: List<String>, // 역할 정보 추가
        httpServletResponse: HttpServletResponse,
    ): String {
        val token = generateToken(subject, nickname, email, roles, Duration.ofHours(accessTokenExpirationHour))
        addTokenToCookie(token, httpServletResponse)
        return token
    }

    fun generateAccessToken(
        subject: String,
        nickname: String,
        email: String,
        roles: List<String>, // 역할 정보 추가
    ): String {
        return generateToken(subject, nickname, email, roles, Duration.ofHours(accessTokenExpirationHour))
    }

    private fun generateToken(
        subject: String,
        nickname: String,
        email: String,
        roles: List<String>, // 역할 정보 추가
        expirationPeriod: Duration,
    ): String {
        val claims: Claims = Jwts.claims()
            .add(mapOf(
                "email" to email,
                "nickname" to nickname,
                "roles" to roles // 역할 정보를 클렘에 포함
            ))
            .build()

        val key = Keys.hmacShaKeyFor(secret.toByteArray(StandardCharsets.UTF_8))
        val now = Instant.now()

        return Jwts.builder()
            .subject(subject)
            .issuer(issuer)
            .issuedAt(Date.from(now))
            .expiration(Date.from(now.plus(expirationPeriod)))
            .claims(claims)
            .signWith(key)
            .compact()
    }

    private fun addTokenToCookie(
        token: String,
        httpServletResponse: HttpServletResponse,
    ) {
        val cookie = Cookie("jwt_token", token)
        cookie.isHttpOnly = false
        cookie.maxAge = (accessTokenExpirationHour * 60 * 60 * 24 * 7).toInt() // 약 8.4일
        cookie.path = "/"
        httpServletResponse.addCookie(cookie)
    }
}

기계녀석의 설명.

 

validateToken(jwt: String): 제공된 JWT의 유효성을 검사합니다. 유효한 토큰인 경우 Jws<Claims>를 반환하고, 그렇지 않을 경우 예외를 발생시킵니다.

generateAccessTokenForSocialUser(...): 소셜 사용자에게 액세스 토큰을 생성하고, 이 토큰을 HTTP 응답의 쿠키에 추가합니다. 사용자의 식별자(subject), 별명(nickname), 이메일(email), 역할(roles)을 기반으로 토큰을 생성합니다.

generateAccessToken(...): 주어진 사용자 정보를 바탕으로 액세스 토큰을 생성합니다. 이 메소드는 generateAccessTokenForSocialUser와 유사하지만, 쿠키에 토큰을 추가하는 작업은 수행하지 않습니다.

generateToken(...): 실제로 JWT를 생성하는 핵심 메소드입니다. 사용자 정보와 만료 기간을 받아 JWT를 생성하고 반환합니다. Jwts.builder()를 사용하여 토큰을 생성합니다.

addTokenToCookie(token: String, httpServletResponse: HttpServletResponse): 생성된 토큰을 HTTP 응답의 쿠키에 추가하는 메소드입니다. 쿠키의 이름은 jwt_token이며, HttpOnly 속성을 false로 설정하여 JavaScript를 통해 쿠키에 접근할 수 있도록 합니다. 쿠키의 유효 기간은 액세스 토큰의 만료 시간과 동일하게 설정됩니다.

 

그런데, 어드민을 일반 유저와 구분하기 위해 role을 찿아보는 중이다.

 

그리고 실행파일을 

@EnableJpaAuditing
@EnableCaching
@SpringBootApplication
@EnableAsync
class BoardApplication

fun main(args: Array<String>) {
    runApplication<BoardApplication>(*args)
}

 

이렇게 만들어 보았다.

 

spring:
  datasource:
    url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    username: sa
    password:
    driver-class-name: org.h2.Driver
  h2:
    console:
      enabled: true
      path: /h2-console

어플리케이션 .yml도 이렇게 만들면 h2를 사용할수있다.

 

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'adminController' defined in file [C:\Users\asdf\IdeaProjects\Board\build\classes\kotlin\main\org\example\domain\admin\controller\AdminController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'adminServiceImpl' defined in file [C:\Users\asdf\IdeaProjects\Board\build\classes\kotlin\main\org\example\domain\admin\service\AdminServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 2: Error creating bean with name 'jwtPlugin' defined in file [C:\Users\asdf\IdeaProjects\Board\build\classes\kotlin\main\org\example\domain\infra\jwt\JwtPlugin.class]: Unexpected exception during bean creation

 

왠지모르겠는 오류 발생해서 jwt를 더 추가해보기로 함