Compare commits

...

2 Commits

Author SHA1 Message Date
728eca6dd6 Merge remote-tracking branch 'upstream/dev' into 0002343-endpoint-tessere 2025-02-18 12:55:00 +01:00
b8ee25b762 modifiche uso JWT
utilizzo dipendenze come da documentazione Ktor per JWT
recupero secret da file di configurazione (e non da database)
2025-02-18 12:50:02 +01:00
5 changed files with 70 additions and 66 deletions

View File

@ -35,9 +35,8 @@ dependencies {
implementation("org.jetbrains.exposed:exposed-dao:$exposed_version") implementation("org.jetbrains.exposed:exposed-dao:$exposed_version")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
implementation ("org.jetbrains.exposed:exposed-java-time:$exposed_version") implementation ("org.jetbrains.exposed:exposed-java-time:$exposed_version")
implementation("io.jsonwebtoken:jjwt-api:0.11.5") implementation("io.ktor:ktor-server-auth:$ktor_version")
implementation("io.jsonwebtoken:jjwt-impl:0.11.5") implementation("io.ktor:ktor-server-auth-jwt:$ktor_version")
implementation("io.jsonwebtoken:jjwt-jackson:0.11.5")
testImplementation("io.ktor:ktor-server-test-host-jvm") testImplementation("io.ktor:ktor-server-test-host-jvm")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
} }

View File

@ -1,7 +1,6 @@
package eu.maiora package eu.maiora
import eu.maiora.plugins.configureDatabases import eu.maiora.plugins.configureDatabases
//import eu.maiora.model.LogScriptRepositoryImpl
import eu.maiora.plugins.* import eu.maiora.plugins.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -21,11 +20,10 @@ fun Application.module() {
val dbUrl = config.property("ktor.database.url").getString(); val dbUrl = config.property("ktor.database.url").getString();
val username = config.property("ktor.database.username").getString(); val username = config.property("ktor.database.username").getString();
val password = config.property("ktor.database.password").getString(); val password = config.property("ktor.database.password").getString();
//val repository = LogScriptRepositoryImpl()
configureDatabases(dbUrl, username, password) configureDatabases(dbUrl, username, password)
//configureRouting(dbUrl, username, password, repository)
configureRouting(dbUrl, username, password) configureRouting(dbUrl, username, password)
configureSerialization() configureSerialization()
install(CallLogging) install(CallLogging)
install(CORS){ install(CORS){
anyHost() anyHost()

View File

@ -18,9 +18,6 @@ fun Application.configureRouting(dbUrl : String, username : String, password : S
call.respondText("Hello World!") call.respondText("Hello World!")
} }
auth(AccountsRepositoryImpl(), ParametriRepositoryImpl()) auth(AccountsRepositoryImpl())
//analizzaURLRoute()
//eseguiScriptSQLRoute(dbUrl, username, password)
//logScriptRouting(repository)
} }
} }

View File

@ -1,13 +1,11 @@
package eu.maiora.routes package eu.maiora.routes
import com.fasterxml.jackson.databind.ser.Serializers.Base import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import eu.maiora.model.AccountsRepositoryImpl import eu.maiora.model.AccountsRepositoryImpl
import eu.maiora.model.ParametriRepositoryImpl
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.config.*
import io.ktor.server.request.* import io.ktor.server.request.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
@ -17,70 +15,77 @@ import org.slf4j.LoggerFactory
import java.util.* import java.util.*
fun Route.auth(accountsRepository: AccountsRepositoryImpl, parametriRepository: ParametriRepositoryImpl){ fun Route.auth(accountsRepository: AccountsRepositoryImpl) {
route("/auth") {
post("/auth"){ post() {
// Riceve il body della richiesta e lo deserializza in ReceivedResponse // Riceve il body della richiesta e lo deserializza in ReceivedResponse
val receivedResponse = try { val receivedResponse = try {
call.receive<ReceivedResponse>() call.receive<ReceivedResponse>()
} catch (e: Exception) { } catch (e: Exception) {
return@post call.respondText("Body mancante " + e.stackTraceToString(), status = HttpStatusCode.BadRequest) return@post call.respondText(
} "Body mancante " + e.stackTraceToString(),
val logger = LoggerFactory.getLogger("AuthRoute") status = HttpStatusCode.BadRequest
logger.info("param: " +
receivedResponse.param);
// Decodifica la stringa da Base64 a oggetto Credentials
val decodedBytes = Base64.getDecoder().decode(receivedResponse.param)
val decodedString = String(decodedBytes)
val credentials = Json.decodeFromString<Credentials>(decodedString)
//verifica credenziali (recupero account dal database)
val account = accountsRepository.accountByUsername(credentials.username)
//se le credenziali sono valide, creare il JWT
if (account != null) {
val passwordPlain = String(
Base64.getDecoder().decode(
StringBuffer(
String(
Base64.getDecoder().decode(account.password.toByteArray())
)
).reverse().toString().toByteArray()
) )
) }
if(passwordPlain.equals(credentials.password)){ val logger = LoggerFactory.getLogger("AuthRoute")
val parametro = parametriRepository.parametroByChiave("jwt_secret") logger.info(
if (parametro != null) { "param: " +
receivedResponse.param
);
// Decodifica la stringa da Base64 a oggetto Credentials
val decodedBytes = Base64.getDecoder().decode(receivedResponse.param)
val decodedString = String(decodedBytes)
val credentials = try {
Json.decodeFromString<Credentials>(decodedString)
} catch (e: Exception) {
return@post call.respondText(
"Errore nel param. Verificare la codifica. \n" + e.stackTraceToString(),
status = HttpStatusCode.BadRequest
)
}
//verifica credenziali (recupero account dal database)
val account = accountsRepository.accountByUsername(credentials.username)
//se le credenziali sono valide, creare il JWT
if (account != null) {
val passwordPlain = String(
Base64.getDecoder().decode(
StringBuffer(
String(
Base64.getDecoder().decode(account.password.toByteArray())
)
).reverse().toString().toByteArray()
)
)
if (passwordPlain.equals(credentials.password)) {
val config = ApplicationConfig("application.conf")
val secret = config.property("ktor.jwt.secret").getString()
val key = Keys.hmacShaKeyFor(parametro.valore.toByteArray())
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val expiration = now + 86400000 // Scadenza tra 1 giorno (24 ore) val expiration = now + 86400000 // Scadenza tra 1 giorno (24 ore)
val token = Jwts.builder() val token = JWT.create()
.setSubject(account.username) // Soggetto del JWT .withSubject(account.username)
.setIssuedAt(Date(now)) // Data di emissione .withIssuedAt(Date(now))
.setExpiration(Date(expiration)) // Data di scadenza .withExpiresAt(Date(expiration))
.signWith(key, SignatureAlgorithm.HS256) // Firma con una chiave segreta .sign(Algorithm.HMAC256(secret))
.compact()
// Risponde con la stringa decodificata // Risponde con la stringa decodificata
call.respond(HttpStatusCode.OK, token) call.respond(HttpStatusCode.OK, token)
}
} } else {
else { call.respond(HttpStatusCode.Unauthorized)
}
} else {
call.respond(HttpStatusCode.Unauthorized) call.respond(HttpStatusCode.Unauthorized)
} }
}
else {
call.respond(HttpStatusCode.Unauthorized)
}
}
} }
} }
@Serializable @Serializable

View File

@ -13,4 +13,9 @@ ktor {
;username = "EP_DONORIONE" ;username = "EP_DONORIONE"
;password = "ep_donorione" ;password = "ep_donorione"
} }
} jwt {
# secret per JWT generato partendo dalla stringa '?Backend_API*06022025!' codificato in Base64
secret = "P0JhY2tlbmRfQVBJKjA2MDIyMDI1IQ=="
}
}