التفويض والمصادقة في Kotlin: JWT، Spring Security و Ktor

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التفويض والمصادقة في Kotlin: دليل شامل

في تطوير الويب الحديث باستخدام Kotlin، تبدأ أمان التطبيق من التنفيذ الصحيح للمصادقة (التحقق من هوية المستخدم) والتفويض (التحقق من صلاحيات الوصول). في هذه المقالة، سنستعرض الأساليب الرئيسية والمكتبات والأدوات لتنفيذ هذه الآليات على منصات Spring Boot و Ktor.



المفاهيم الأساسية

قبل الانتقال إلى الكود، دعنا نفهم المصطلحات:

  • المصادقة — عملية التحقق من أن المستخدم هو من يدّعي (عادةً عبر اسم المستخدم/كلمة المرور، رمز مميز أو القياسات الحيوية).
  • التفويض — تحديد صلاحيات الوصول للمستخدم المُصادَق عليه (على سبيل المثال، الوصول إلى مسارات أو بيانات معينة).
  • JWT (JSON Web Token) — رمز مميز مضغوط ومكتفي بذاته لنقل البيانات بين الأطراف.
  • BCrypt — خوارزمية تجزئة لكلمات المرور مع ملح، مقاومة لهجمات القوة العمياء.


المصادقة باستخدام JWT في Spring Boot

يوفر Spring Security بنية تحتية قوية للمصادقة. سنستعرض تنفيذ مصادقة JWT باستخدام مكتبة io.jsonwebtoken:jjwt.



// 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

توصيات