首页 > 其他分享 >ktor

ktor

时间:2022-09-22 18:57:28浏览次数:46  
标签:name val 验证 ktor call credentials 请求

1.权限验证

Basic Authentication(基本验证)

注册验证
install(Authentication) {
    basic("auth-basic") {
       // 验证失败返回的消息 
        realm = "you  don't have authority"
       // validate 验证
        validate { credentials ->
       // credentials.name 用户名     
            if (credentials.name =="admin" && credentials.password =="123" ) {
                UserIdPrincipal(credentials.name)
            } else {
                null
            }
        }
    }
}
请求使用

当客户端没有在请求头中 携带 Authorization的验证信息时,服务端会在响应头中携带 WWW-Authenticate,并返回状态码401,告诉用户Unauthorized,如下:

WWW-Authenticate:Basic realm="you  don't have authority", charset=UTF-8

客户端在请求头中携带了 Authorization的验证信息时,服务端会在validate中验证权限是否通过,如果通过则 返回UserIdPrincipal,否则返回null,客户端可以使用Base64对用户名和密码加密:

# 用户名密码格式: 用户名:密码 例如 admin:123 使用base64加密后 就是 YWRtaW46MTIz
# Basic则指明使用哪一种验证方式
Authorization:Basic emhhbnNnYW46MTIz

然后使用路由,我们让get请求不需要验证,post需要。

    routing {
        route("/test") {
            get {
                call.respondText("Hello,哈哈哈")
            }
            authenticate("auth-basic") {
                post {
                    call.respondText("Hello, ${call.principal<UserIdPrincipal>()?.name}!")
                }
            }
        }
    }

这里使用post测试

image

Form Authentication(表单验证)

表单验证的大致流程就是,客户端发送请求,服务端返回给客户端一个表单,填写完成后路由到验证请求进行验证。

注册验证
install(Authentication) { 
	form("auth-form") {
      // 对应表单name 的值
     userParamName = "username"
     passwordParamName = "password"
     validate { credentials ->
         if (credentials.name == "admin" && credentials.password == "123") {
             UserIdPrincipal(credentials.name)
         } else {
             null
         }
     }
  }
}
请求使用

首先 让客户端请求返回表单验证的地址 http://0.0.0.0:8087/authority,后端返回表单代码:

route("/authority") {
    get {
        call.respondHtml(HttpStatusCode.OK) {
            body {
                form {
                    action = "/login"
                    encType = FormEncType.applicationXWwwFormUrlEn
                    // 注意 这里必须是post请求
                    method = FormMethod.post
                    div {
                        "User:"
                    }
                    div {
                        input {
                            type = InputType.text
                            name = "username"
                        }
                    }
                    div {
                        "Password:"
                    }
                    div {
                        input {
                            type = InputType.text
                            name = "password"
                        }
                    }
                    div {
                        input {
                            type = InputType.submit
                            value = "Login"
                        }
                    }
                }
            }
        }
    }
}

然后会弹出输入框,输入用户名密码验证

image

当跳转到login时,会验证 username和password

route("/login") {
    authenticate("auth-form") {
        // 注意 这里必须是post请求
        post {
            call.respondText("Hello, ${call.principal<UserIdPrincipal>()?.name}!")
        }
    }
}

Json Web Token

jwt的大致流程就是 第一次登录 请求成功后,服务端会生成一个token 给客户端,客户端可以在请求的时候请求头携带token访问被保护的资源

注册验证
val secret = globalEnvironment.config.getMandatoryString("jwt.secret")
val issuer = globalEnvironment.config.getMandatoryString("jwt.issuer")
val audience = globalEnvironment.config.getMandatoryString("jwt.audience")
val myRealm = globalEnvironment.config.getMandatoryString("jwt.realm")

install(Authentication) {
	jwt("auth-jwt") {
    // 验证token
    realm=myRealm
    verifier(JWT
            .require(Algorithm.HMAC256(secret))
            .withAudience(audience)
            .withIssuer(issuer)
            .build()
    )
    validate {
        credential->
        if (credential.payload.getClaim("username").asString() != "") {
            JWTPrincipal(credential.payload)
        } else {
            null
        }
    }
}  
  
}

访问登录接口获取token

routing {
    post("/jwt/login") {
        val user = JSON.parseObject(call.receiveText())
        val token = JWT.create()
            .withAudience(audience)
            .withIssuer(issuer)
            .withClaim("username", user["username"].toString())
            .withExpiresAt(Date(System.currentTimeMillis() + 6000000))
            .sign(Algorithm.HMAC256(secret))
        call.respond(mapOf("token" to token))
	}
}

访问被保护资源验证

authenticate("auth-jwt") {
    get("/resources"){
        val principal = call.principal<JWTPrincipal>()
        val username = principal!!.payload.getClaim("username").asString()
        val expiresAt = principal.expiresAt?.time?.minus(System.currentTimeMillis())
        call.respondText("Hello, $username! Token is expired at $expiresAt ms.")
    }
}

postman请求

请求头中携带格式

Authorization:Bearer token字符串

image

2.日志

使用 CallLogging 可以起到类似于 java aop切面编程的作用

使用如下

fun Application.configureLog() {
    install(CallLogging) {
        // 日至等级
        level = Level.INFO
        // 过滤请求
        filter { call ->
            println(call.request.path())
            call.request.path().contains("log")
        }
        // 自定义日志消息
        format { call ->
            runBlocking {
                val uri = call.request.path()
                val status = call.response.status()
                val httpMethod = call.request.httpMethod.value
                val params = call.request.queryParameters.toMap().entries.associate { it.key to it.value[0] }.toString()
                val bodyParams = call.receiveText()
                "path:$uri,Method:$httpMethod,params:$bodyParams,responseStatus:$status"
            }

        }
    }

}

标签:name,val,验证,ktor,call,credentials,请求
From: https://www.cnblogs.com/wlstudy09/p/16720498.html

相关文章