konstruktivnie_jwt_generate_validate

This commit is contained in:
Your Name 2025-03-11 10:38:40 +03:00
parent 50646861e6
commit d92f5a2d5d
4 changed files with 83 additions and 107 deletions

View File

@ -48,6 +48,9 @@ dependencies {
implementation("io.ktor:ktor-server-content-negotiation:2.3.4")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("com.auth0:java-jwt:4.4.0")
implementation("io.ktor:ktor-server-auth:2.3.4")
implementation("io.ktor:ktor-server-auth-jwt:2.3.4")
}
tasks.test {

View File

@ -1,6 +1,5 @@
package com.example
import com.example.*
import io.ktor.http.*
import io.ktor.server.application.*
@ -21,6 +20,12 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual
import java.math.BigDecimal
import java.util.*
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.config.*
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
@ -51,6 +56,27 @@ fun Application.configureSerialization() {
}
})
}
install(Authentication) {
jwt("auth-jwt") {
verifier(
JWT.require(Algorithm.HMAC256("secret"))
.withIssuer("http://localhost:8080")
.withAudience("http://localhost:8080/mainWindow") // Должно совпадать
.build()
)
validate { credential ->
if (credential.payload.getClaim("email").asString() != "") {
JWTPrincipal(credential.payload)
} else {
null
}
}
challenge { _, _ ->
call.respond(HttpStatusCode.Unauthorized, "Token is not valid or has expired")
}
}
}
}
fun Application.configureRouting() {
@ -58,7 +84,7 @@ fun Application.configureRouting() {
post("/register") {
val request = call.receive<UserRegisterRequest>()
if (AuthService.registerUser(request.name, request.email, request.password)) {
call.respond(mapOf("message" to "Регистрация успешна"))
call.respond(mapOf("Email" to "Успешно"))
} else {
call.respond(mapOf("error" to "Email уже зарегистрирован"))
}
@ -66,10 +92,34 @@ fun Application.configureRouting() {
post("/login") {
val request = call.receive<UserLoginRequest>()
try {
if (AuthService.loginUser(request.email, request.password)) {
call.respond(mapOf("message" to "Вход успешен"))
} else {
call.respond(mapOf("error" to "Неверный email или пароль"))
// val jwtSecret = environment.config.propertyOrNull("jwt.secret")?.getString()
val jwtSecret = "secret"
?: throw ApplicationConfigurationException("jwt.secret not found")
log.info("JWT Secret: $jwtSecret")
// val jwtIssue = environment.config.propertyOrNull("jwt.issue")?.getString()
val jwtIssue = "http://localhost:8080"
?: throw ApplicationConfigurationException("jwt.issue not found")
log.info("JWT Issue: $jwtIssue")
// val jwtAudience = environment.config.propertyOrNull("jwt.audience")?.getString()
val jwtAudience = "http://localhost:8080/mainWindow"
?: throw ApplicationConfigurationException("jwt.audience not found")
log.info("JWT Audience: $jwtAudience")
val token = JWT.create()
.withIssuer(jwtIssue)
.withAudience(jwtAudience)
.withClaim("email", request.email)
.withExpiresAt(Date(System.currentTimeMillis() + 10 * 60000))
.sign(Algorithm.HMAC256(jwtSecret))
call.respond(mapOf("Token" to token))
}
} catch (e: Exception) {
log.error("Error fetching sneakers: ${e.message}", e)
call.respond(HttpStatusCode.InternalServerError, "Error: ${e.message}")
}
}
@ -94,40 +144,29 @@ fun Application.configureRouting() {
}
}
post("/reset-passwor") {
val request = call.receive<UserResetPasswordRequest>()
if (AuthService.resetPassword(request.code, request.newPassword)) {
call.respond(mapOf("message" to "Пароль успешно изменён"))
} else {
call.respond(mapOf("error" to "Неверный код"))
}
}
authenticate("auth-jwt"){
get("/mainWindow") {
try {
val principal = call.principal<JWTPrincipal>()
val userEmail = principal?.payload?.getClaim("email")?.asString()
// get ("/mainWindow"){
// val sneakers = AuthService.selectSneakers()
// call.respond(mapOf("sneaker" to sneakers))
// }
if (userEmail == null) {
call.respond(HttpStatusCode.Unauthorized, "Invalid token")
return@get
}
// get("/mainWindow") {
// try {
// // Ваш код для обработки запроса
// call.respondText("Main Window Content")
// } catch (e: Exception) {
// call.respond(HttpStatusCode.InternalServerError, "Error: ${e.message}")
// }
// }
log.info("User $userEmail is accessing /mainWindow")
get("/mainWindow") {
try {
val sneakers = AuthService.selectSneakers()
if (sneakers.isNotEmpty()) {
call.respond(mapOf("sneakers" to sneakers))
} else {
call.respond(mapOf("error" to "No sneakers found"))
val sneakers = AuthService.selectSneakers()
if (sneakers.isNotEmpty()) {
call.respond(mapOf("sneakers" to sneakers))
} else {
call.respond(mapOf("error" to "No sneakers found"))
}
} catch (e: Exception) {
log.error("Error fetching sneakers: ${e.message}", e)
call.respond(HttpStatusCode.InternalServerError, "Error: ${e.message}")
}
} catch (e: Exception) {
log.error("Error fetching sneakers: ${e.message}", e)
call.respond(HttpStatusCode.InternalServerError, "Error: ${e.message}")
}
}
}

View File

@ -1,75 +1,3 @@
//package com.example
//
//import at.favre.lib.crypto.bcrypt.BCrypt
//import org.jetbrains.exposed.sql.*
//import org.jetbrains.exposed.sql.transactions.transaction
//import java.util.UUID
//
//object AuthService {
//
// fun registerUser(name: String, email: String, password: String): Boolean {
// val hashedPassword = hashPassword(password)
// return transaction {
// if (Users.select { Users.email eq email }.empty()) {
// Users.insert {
// it[Users.name] = name
// it[Users.email] = email
// it[Users.passwordHash] = hashedPassword
// }
// true
// } else {
// false
// }
// }
// }
//
// fun loginUser(email: String, password: String): Boolean {
// val user = transaction {
// Users.select { Users.email eq email }
// .mapNotNull { it[Users.passwordHash] }
// .firstOrNull()
// }
// return user != null && checkPassword(password, user)
// }
//
// fun generateResetToken(email: String): String? {
// val token = UUID.randomUUID().toString()
// return transaction {
// val updatedRows = Users.update({ Users.email eq email }) {
// it[resetToken] = token
// }
// if (updatedRows > 0) token else null
// }
// }
//
// fun resetPassword(token: String, newPassword: String): Boolean {
// return transaction {
// val email = Users.select { Users.resetToken eq token }
// .mapNotNull { it[Users.email] }
// .firstOrNull()
//
// if (email != null) {
// val hashedPassword = hashPassword(newPassword)
// Users.update({ Users.email eq email }) {
// it[passwordHash] = hashedPassword
// it[resetToken] = null
// }
// true
// } else {
// false
// }
// }
// }
//
// private fun hashPassword(password: String): String {
// return BCrypt.withDefaults().hashToString(12, password.toCharArray())
// }
//
// private fun checkPassword(password: String, hash: String): Boolean {
// return BCrypt.verifyer().verify(password.toCharArray(), hash).verified
// }
//}
package com.example
import at.favre.lib.crypto.bcrypt.BCrypt

View File

@ -0,0 +1,6 @@
jwt {
secret = "secret"
issue = "http://localhost:8080"
audience = "http://localhost:8080/test" // временная строка
realm = "Access to 'hello'"
}