Kotlin 中的授权与认证:JWT、Spring Security 和 Ktor

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin 中的授权与认证:完整指南

在现代 Kotlin Web 开发中,应用程序的安全性始于正确实现认证(验证用户身份)和授权(验证访问权限)。在本文中,我们将探讨在 Spring Boot 和 Ktor 平台上实现这些机制的主要方法、库和工具。



基本概念

在进入代码之前,我们先了解一些术语:

  • 认证 — 验证用户是否为其所声称的身份的过程(通常通过登录名/密码、令牌或生物识别)。
  • 授权 — 确定已认证用户的访问权限(例如,访问特定路由或数据)。
  • JWT(JSON Web Token) — 一种紧凑且自包含的令牌,用于在各方之间传输数据。
  • BCrypt — 一种带盐的密码哈希算法,能够抵抗暴力攻击。


在 Spring Boot 中使用 JWT 进行认证

Spring Security 为认证提供了强大的基础设施。让我们看看如何使用 io.jsonwebtoken:jjwt 库实现 JWT 认证。



// build.gradle.ktsdependencies {    implementation("org.springframework.boot:spring-boot-starter-security")    implementation("io.jsonwebtoken:jjwt-api:0.12.3")    runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3")    runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")}


创建一个用于处理 JWT 的工具类:



import io.jsonwebtoken.*import io.jsonwebtoken.security.Keysimport org.springframework.stereotype.Componentimport java.security.Keyimport java.util.*

@Componentclass JwtUtil { private val secretKey: Key = Keys.secretKeyFor(SignatureAlgorithm.HS256) private val expirationMs: Long = 3600000 // 1 小时

fun generateToken(username: String): String { return Jwts.builder() .subject(username) .issuedAt(Date()) .expiration(Date(System.currentTimeMillis() + expirationMs)) .signWith(secretKey) .compact() }

fun extractUsername(token: String): String? { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token).payload.subject } catch (e: Exception) { null } }

fun validateToken(token: String): Boolean { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token) true } catch (e: JwtException) { false } }}


Spring Security 的认证过滤器

现在创建一个过滤器,用于拦截请求并验证 JWT 令牌:



import jakarta.servlet.FilterChainimport jakarta.servlet.http.HttpServletRequestimport jakarta.servlet.http.HttpServletResponseimport org.springframework.security.authentication.UsernamePasswordAuthenticationTokenimport org.springframework.security.core.context.SecurityContextHolderimport org.springframework.security.web.authentication.WebAuthenticationDetailsSourceimport org.springframework.stereotype.Componentimport org.springframework.web.filter.OncePerRequestFilter

@Componentclass JwtAuthFilter( private val jwtUtil: JwtUtil, private val userDetailsService: org.springframework.security.core.userdetails.UserDetailsService) : OncePerRequestFilter() {

override fun doFilterInternal( request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain ) { val authHeader = request.getHeader("Authorization") if (authHeader == null || !authHeader.startsWith("Bearer ")) { chain.doFilter(request, re

推荐