移除FreeMarker

This commit is contained in:
Raymond Yang 2023-06-21 13:32:57 +08:00
parent df2b630175
commit a361978101
8 changed files with 67 additions and 78 deletions

View File

@ -23,12 +23,11 @@ repositories {
dependencies {
implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
implementation("io.ktor:ktor-server-cors:$ktor_version")
implementation("io.ktor:ktor-server-auth-jvm:$ktor_version")
implementation("io.ktor:ktor-server-auth-jwt-jvm:$ktor_version")
implementation("io.ktor:ktor-server-sessions-jvm:$ktor_version")
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
implementation("io.ktor:ktor-serialization-gson-jvm:$ktor_version")
implementation("io.ktor:ktor-server-freemarker-jvm:$ktor_version")
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")

View File

@ -2,6 +2,8 @@ package com.ray650128
import io.ktor.server.application.*
import com.ray650128.plugins.*
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
fun main(args: Array<String>): Unit =
io.ktor.server.netty.EngineMain.main(args)
@ -10,6 +12,27 @@ fun main(args: Array<String>): Unit =
fun Application.module() {
configureSecurity()
configureSerialization()
configureTemplating()
configureRouting()
}
fun md5encode(password: String): String {
try {
val instance: MessageDigest = MessageDigest.getInstance("MD5") // 獲取md5加密對象
val digest:ByteArray = instance.digest(password.toByteArray()) // 對字串加密,返回字節數組
val sb = StringBuffer()
for (b in digest) {
val i :Int = b.toInt() and 0xff // 獲取低八位有效值
var hexString = Integer.toHexString(i) // 將整數轉化爲16進制
if (hexString.length < 2) {
hexString = "0$hexString" // 如果是一位的話補0
}
sb.append(hexString)
}
return sb.toString()
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
}
return ""
}

View File

@ -7,16 +7,17 @@ import com.ray650128.model.User
import java.util.*
object JwtConfig {
val secret = "my-secret"
val issuer = "com.ray650128"
val myRealm = "com.ray650128"
val jwtAudience = "jwt-audience"
val jwtDomain = "com.ray650128"
val jwtRealm = "pc re:dive rank table"
val jwtSecret = "secret"
//private val validityInMs = 36_000_00 * 24 // 1 day
private val validityInMs = 300000 // 5 min
private val algorithm = Algorithm.HMAC512(secret)
private const val validityInMs = 300000 // 5 min
private val algorithm = Algorithm.HMAC512(jwtSecret)
val verifier: JWTVerifier = JWT
.require(algorithm)
.withIssuer(issuer)
.withIssuer(jwtDomain)
.build()
/**
@ -24,7 +25,7 @@ object JwtConfig {
*/
fun generateToken(user: User): String = JWT.create()
.withSubject("Authentication")
.withIssuer(issuer)
.withIssuer(jwtDomain)
.withClaim("account", user.account)
.withExpiresAt(getExpiration()) // optional
.sign(algorithm)

View File

@ -1,21 +1,38 @@
package com.ray650128.plugins
import com.ray650128.JwtConfig
import com.ray650128.extensions.sendBadRequest
import com.ray650128.extensions.sendCreated
import com.ray650128.extensions.sendSuccess
import com.ray650128.extensions.sendUnauthorized
import com.ray650128.extensions.*
import com.ray650128.md5encode
import com.ray650128.model.ErrorResponse
import com.ray650128.model.LoginResult
import com.ray650128.model.User
import com.ray650128.service.UserService
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.plugins.cors.routing.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.io.File
fun Application.configureRouting() {
install(CORS) {
allowHeader(HttpHeaders.AccessControlAllowOrigin)
allowHeader(HttpHeaders.Accept)
allowHeader(HttpHeaders.ContentType)
anyHost()
allowMethod(HttpMethod.Options)
allowMethod(HttpMethod.Get)
allowMethod(HttpMethod.Post)
allowMethod(HttpMethod.Put)
allowMethod(HttpMethod.Delete)
allowHeader(HttpHeaders.Authorization)
allowCredentials = true
allowNonSimpleContentTypes = true
}
routing {
route("/api") {
route("/v1") {
@ -26,9 +43,11 @@ fun Application.configureRouting() {
return@post
}
val newToken = JwtConfig.generateToken(request)
val user = request.apply {
val user = User(
account = request.account,
password = md5encode(request.password),
createAt = System.currentTimeMillis()
}
)
UserService.create(user)?.let { userId ->
call.response.headers.append("My-User-Id-Header", userId.toString())
call.sendCreated(LoginResult(request.account, newToken))
@ -37,12 +56,13 @@ fun Application.configureRouting() {
post("/login") {
val request = call.receive<User>()
val user = UserService.findByLoginInfo(request.account, request.password)
val password = md5encode(request.password)
val user = UserService.findByLoginInfo(request.account, password)
if (user != null) {
val token = JwtConfig.generateToken(request)
call.sendSuccess(LoginResult(request.account, token))
} else {
call.sendBadRequest(ErrorResponse("Account or Password wrong."))
call.sendUnauthorized()
}
}

View File

@ -4,6 +4,7 @@ import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.ray650128.JwtConfig
import io.ktor.server.sessions.*
import io.ktor.server.response.*
import io.ktor.server.application.*
@ -11,37 +12,15 @@ import io.ktor.server.routing.*
fun Application.configureSecurity() {
// Please read the jwt property from the config file if you are using EngineMain
val jwtAudience = "jwt-audience"
val jwtDomain = "https://jwt-provider-domain/"
val jwtRealm = "ktor sample app"
val jwtSecret = "secret"
authentication {
jwt {
realm = jwtRealm
verifier(
JWT
.require(Algorithm.HMAC256(jwtSecret))
.withAudience(jwtAudience)
.withIssuer(jwtDomain)
.build()
)
realm = JwtConfig.jwtRealm
verifier(JwtConfig.verifier)
validate { credential ->
if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
if (credential.payload.audience.contains(JwtConfig.jwtAudience)) {
JWTPrincipal(credential.payload)
} else null
}
}
}
data class MySession(val count: Int = 0)
install(Sessions) {
cookie<MySession>("MY_SESSION") {
cookie.extensions["SameSite"] = "lax"
}
}
routing {
get("/session/increment") {
val session = call.sessions.get<MySession>() ?: MySession()
call.sessions.set(session.copy(count = session.count + 1))
call.respondText("Counter is ${session.count}. Refresh to increment.")
}
}
}

View File

@ -1,20 +0,0 @@
package com.ray650128.plugins
import freemarker.cache.*
import io.ktor.server.freemarker.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
fun Application.configureTemplating() {
install(FreeMarker) {
templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
}
routing {
get("/html-freemarker") {
call.respond(FreeMarkerContent("index.ftl", mapOf("data" to IndexData(listOf(1, 2, 3))), ""))
}
}
}
data class IndexData(val items: List<Int>)

View File

@ -7,8 +7,3 @@ ktor {
modules = [ com.ray650128.ApplicationKt.module ]
}
}
jwt {
domain = "https://jwt-provider-domain/"
audience = "jwt-audience"
realm = "ktor sample app"
}

View File

@ -1,8 +0,0 @@
<html>
<body>
<h1>Items:</h1>
<#list data.items as item>
<h2>The item at index ${item?index} is ${item}</h2>
</#list>
</body>
</html>