MST

星途 面试题库

面试题:Kotlin的Ktor框架中如何实现自定义认证机制

在使用Kotlin和Ktor框架开发的项目里,要求实现一个基于JWT(JSON Web Token)的自定义认证机制。描述实现思路并给出关键代码片段,包括如何生成、验证JWT,以及如何在Ktor的路由中使用这个认证机制。
43.2万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 生成JWT
    • 选择一个JWT库,如jjwt库。
    • 定义需要放入JWT载荷(payload)的信息,如用户ID、用户名等。
    • 使用库提供的方法,结合密钥(secret key)生成JWT。
  2. 验证JWT
    • 在收到请求时,从请求头(通常是Authorization头,格式为Bearer <token>)提取JWT。
    • 使用相同的JWT库,结合密钥验证JWT的签名和有效性(如过期时间等)。
  3. 在Ktor路由中使用认证机制
    • 创建一个拦截器(interceptor),在拦截器中进行JWT的验证。
    • 对于需要认证的路由,应用这个拦截器。

关键代码片段

  1. 引入依赖build.gradle.kts文件中添加jjwt库的依赖:
dependencies {
    implementation("io.jsonwebtoken:jjwt-api:0.11.2")
    runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
    runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
}
  1. 生成JWT
import io.jsonwebtoken.Claims
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import java.security.Key
import java.util.Date

private val key: Key = Keys.secretKeyFor(SignatureAlgorithm.HS256)
private const val EXPIRATION_TIME = 3600000L // 1 hour in milliseconds

fun generateToken(userId: String, username: String): String {
    val expiration = Date(System.currentTimeMillis() + EXPIRATION_TIME)
    val claims: Claims = Jwts.claims().apply {
        put("userId", userId)
        put("username", username)
    }
    return Jwts.builder()
      .setClaims(claims)
      .setIssuedAt(Date())
      .setExpiration(expiration)
      .signWith(key, SignatureAlgorithm.HS256)
      .compact()
}
  1. 验证JWT
import io.jsonwebtoken.Claims
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.security.Keys
import java.security.Key

private val key: Key = Keys.secretKeyFor(SignatureAlgorithm.HS256)

fun validateToken(token: String): Boolean {
    return try {
        val claims: Claims = Jwts.parserBuilder()
          .setSigningKey(key)
          .build()
          .parseClaimsJws(token)
          .body
        true
    } catch (e: Exception) {
        false
    }
}
  1. 在Ktor路由中使用认证机制
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*

fun Application.configureRouting() {
    routing {
        intercept(ApplicationCallPipeline.Features) {
            val token = call.request.headers[HttpHeaders.Authorization]?.substringAfter("Bearer ")
            if (token == null ||!validateToken(token)) {
                call.respond(HttpStatusCode.Unauthorized)
                return@intercept
            }
        }
        get("/protected") {
            call.respondText("This is a protected route")
        }
    }
}