加入登出功能
This commit is contained in:
parent
9237736067
commit
64c987f6c0
@ -12,5 +12,4 @@ fun Application.module() {
|
|||||||
DatabaseFactory.init()
|
DatabaseFactory.init()
|
||||||
DatabaseFactory.createTable()
|
DatabaseFactory.createTable()
|
||||||
configureRouting()
|
configureRouting()
|
||||||
configureSecurity()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.ray650128.model
|
package com.ray650128.model
|
||||||
|
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
|
||||||
data class User(
|
data class User(
|
||||||
var id: Long? = -1,
|
var id: Long? = -1,
|
||||||
var name: String? = "",
|
var name: String? = "",
|
||||||
@ -8,4 +10,4 @@ data class User(
|
|||||||
var token: String? = "",
|
var token: String? = "",
|
||||||
var createTime: Long? = -1,
|
var createTime: Long? = -1,
|
||||||
var updateTime: Long? = -1
|
var updateTime: Long? = -1
|
||||||
)
|
): Principal
|
||||||
|
|||||||
@ -2,19 +2,34 @@ package com.ray650128.plugins
|
|||||||
|
|
||||||
import com.ray650128.model.LoginBody
|
import com.ray650128.model.LoginBody
|
||||||
import com.ray650128.model.User
|
import com.ray650128.model.User
|
||||||
import com.ray650128.repository.UserRepository
|
import com.ray650128.service.UserService
|
||||||
import io.ktor.server.routing.*
|
import com.ray650128.utils.JwtConfig
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.serialization.gson.*
|
import io.ktor.serialization.gson.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.auth.jwt.*
|
||||||
import io.ktor.server.plugins.contentnegotiation.*
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
import io.ktor.server.response.*
|
|
||||||
import io.ktor.server.request.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Application.configureRouting() {
|
fun Application.configureRouting() {
|
||||||
|
|
||||||
val userRepository = UserRepository()
|
install(Authentication) {
|
||||||
|
jwt {
|
||||||
|
verifier(JwtConfig.verifier)
|
||||||
|
realm = JwtConfig.myRealm
|
||||||
|
validate {
|
||||||
|
val name = it.payload.getClaim("account").asString()
|
||||||
|
if (name != null) {
|
||||||
|
User(account = name, password = "")
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
gson {
|
gson {
|
||||||
}
|
}
|
||||||
@ -26,16 +41,86 @@ fun Application.configureRouting() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post("/api/v1/register") {
|
post("/api/v1/register") {
|
||||||
|
val body = call.receive<LoginBody>()
|
||||||
|
val token = JwtConfig.generateToken(body)
|
||||||
|
val data = User(
|
||||||
|
account = body.account,
|
||||||
|
password = body.password,
|
||||||
|
token = token
|
||||||
|
)
|
||||||
|
val result = UserService().addUser(data)
|
||||||
|
if (result) {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.OK,
|
||||||
|
message = mapOf("token" to token)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.BadRequest,
|
||||||
|
message = mapOf("message" to "User has exist.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post("/api/v1/login") {
|
||||||
val body = call.receive<LoginBody>()
|
val body = call.receive<LoginBody>()
|
||||||
val data = User(
|
val data = User(
|
||||||
account = body.account,
|
account = body.account,
|
||||||
password = body.password
|
password = body.password
|
||||||
)
|
)
|
||||||
userRepository.add(data)
|
// Check username and password
|
||||||
call.respond(
|
val user = UserService().getUser(data)
|
||||||
status = HttpStatusCode.OK,
|
if (user != null) {
|
||||||
message = mapOf("token" to "aaaaaaa")
|
var token = user.token
|
||||||
)
|
if (token.isNullOrEmpty()) {
|
||||||
|
token = JwtConfig.generateToken(body)
|
||||||
|
user.token = token
|
||||||
|
UserService().updateUser(user)
|
||||||
|
}
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.OK,
|
||||||
|
message = mapOf("token" to token)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.Unauthorized,
|
||||||
|
message = mapOf("message" to "Account or Password wrong.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate {
|
||||||
|
post("/api/v1/updateUser") {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.OK,
|
||||||
|
message = mapOf("message" to "Test.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post("/api/v1/logout") {
|
||||||
|
val account = call.authentication.principal<User>()?.account
|
||||||
|
println("[Logout] Account: $account")
|
||||||
|
if (account.isNullOrEmpty()) {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.Unauthorized,
|
||||||
|
message = mapOf("message" to "Unauthorized.")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val user = UserService().getUserByAccount(account)
|
||||||
|
if (user != null) {
|
||||||
|
user.token = null
|
||||||
|
UserService().updateUser(user)
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.OK,
|
||||||
|
message = mapOf("message" to "success.")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
call.respond(
|
||||||
|
status = HttpStatusCode.Unauthorized,
|
||||||
|
message = mapOf("message" to "Unauthorized.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class UserRepository {
|
|||||||
Users.insert {
|
Users.insert {
|
||||||
it[account] = data.account
|
it[account] = data.account
|
||||||
it[password] = data.password
|
it[password] = data.password
|
||||||
|
it[token] = data.token
|
||||||
it[createTime] = System.currentTimeMillis()
|
it[createTime] = System.currentTimeMillis()
|
||||||
it[updateTime] = System.currentTimeMillis()
|
it[updateTime] = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
@ -40,7 +41,18 @@ class UserRepository {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun get(userAccount: String): User? {
|
suspend fun get(data: User): User? {
|
||||||
|
return transaction {
|
||||||
|
Users.select {
|
||||||
|
Users.account eq data.account
|
||||||
|
Users.password eq data.password
|
||||||
|
}.mapNotNull {
|
||||||
|
toUser(it)
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getByAccount(userAccount: String): User? {
|
||||||
return transaction {
|
return transaction {
|
||||||
Users.select { Users.account eq userAccount }.mapNotNull {
|
Users.select { Users.account eq userAccount }.mapNotNull {
|
||||||
toUser(it)
|
toUser(it)
|
||||||
|
|||||||
@ -7,11 +7,23 @@ class UserService {
|
|||||||
val userRepository = UserRepository()
|
val userRepository = UserRepository()
|
||||||
|
|
||||||
suspend fun addUser(data: User): Boolean {
|
suspend fun addUser(data: User): Boolean {
|
||||||
return if (userRepository.get(data.account) == null) {
|
return if (userRepository.get(data) == null) {
|
||||||
userRepository.add(data)
|
userRepository.add(data)
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getUser(data: User): User? {
|
||||||
|
return userRepository.get(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getUserByAccount(account: String): User? {
|
||||||
|
return userRepository.getByAccount(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateUser(data: User) {
|
||||||
|
userRepository.update(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
36
src/main/kotlin/com/ray650128/utils/JwtConfig.kt
Normal file
36
src/main/kotlin/com/ray650128/utils/JwtConfig.kt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package com.ray650128.utils
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWT
|
||||||
|
import com.auth0.jwt.JWTVerifier
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm
|
||||||
|
import com.ray650128.model.LoginBody
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object JwtConfig {
|
||||||
|
val secret = "my-secret"
|
||||||
|
val issuer = "com.ray650128"
|
||||||
|
val myRealm = "com.ray650128"
|
||||||
|
private val validityInMs = 36_000_00 * 24 // 1 day
|
||||||
|
private val algorithm = Algorithm.HMAC512(secret)
|
||||||
|
|
||||||
|
val verifier: JWTVerifier = JWT
|
||||||
|
.require(algorithm)
|
||||||
|
.withIssuer(issuer)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produce a token for this combination of name and password
|
||||||
|
*/
|
||||||
|
fun generateToken(user: LoginBody): String = JWT.create()
|
||||||
|
.withSubject("Authentication")
|
||||||
|
.withIssuer(issuer)
|
||||||
|
.withClaim("account", user.account)
|
||||||
|
//.withExpiresAt(getExpiration()) // optional
|
||||||
|
.sign(algorithm)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the expiration Date based on current time + the given validity
|
||||||
|
*/
|
||||||
|
private fun getExpiration() = Date(System.currentTimeMillis() + validityInMs)
|
||||||
|
}
|
||||||
@ -8,7 +8,9 @@ ktor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
jwt {
|
jwt {
|
||||||
domain = "https://jwt-provider-domain/"
|
secret = "secret"
|
||||||
|
domain = "https://www.ray650128.com"
|
||||||
|
issuer = "https://www.ray650128.com/"
|
||||||
audience = "jwt-audience"
|
audience = "jwt-audience"
|
||||||
realm = "ktor sample app"
|
realm = "ktor sample app"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user