实现思路
- 生成JWT:
- 选择一个JWT库,如
jjwt
库。
- 定义需要放入JWT载荷(payload)的信息,如用户ID、用户名等。
- 使用库提供的方法,结合密钥(secret key)生成JWT。
- 验证JWT:
- 在收到请求时,从请求头(通常是
Authorization
头,格式为Bearer <token>
)提取JWT。
- 使用相同的JWT库,结合密钥验证JWT的签名和有效性(如过期时间等)。
- 在Ktor路由中使用认证机制:
- 创建一个拦截器(interceptor),在拦截器中进行JWT的验证。
- 对于需要认证的路由,应用这个拦截器。
关键代码片段
- 引入依赖
在
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")
}
- 生成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()
}
- 验证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
}
}
- 在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")
}
}
}