import kotlinx.serialization.Serializableimport io.ktor.http.*import java.security.MessageDigestimport java.util.*import io.ktor.client.*import io.ktor.client.engine.cio.*import io.ktor.client.features.*import io.ktor.client.features.cookies.*import io.ktor.client.features.json.*import io.ktor.client.features.json.serializer.*import io.ktor.client.features.logging.*import io.ktor.client.request.*import io.ktor.client.statement.*import io.ktor.http.*import kotlinx.coroutines.runBlocking
privateconst val LOGIN ="login"privateconst val PASSWORD ="password"
data classKeeneticAuthHeaderValues(
val map:Map<KeeneticAuthHeaderEnum,String>){
val xndmChallenge:String by lazy {map.getValue(KeeneticAuthHeaderEnum.XNDMChallenge)}
val xndmRealm:String by lazy {map.getValue(KeeneticAuthHeaderEnum.XNDMRealm)}}@Serializable
data classUserCredentials(val login:String, val password:String)
fun Headers.asMap():EnumMap<KeeneticAuthHeaderEnum,String>=EnumMap(
entries().asSequence().filter { it -> it.key in KeeneticAuthHeaderEnum.values().map{ it.title }}.associate { header ->KeeneticAuthHeaderEnum.from(header.key) to header.value.first()})// However, here we have to use a custom byte to hex converter to get the hashed value in hexadecimalprivate fun printHexBinary(hash:ByteArray):String{
val hexString =StringBuilder(2* hash.size)for(i in hash.indices){
val hex =Integer.toHexString(0xff and hash[i].toInt())if(hex.length ==1){
hexString.append('0')}
hexString.append(hex)}return hexString.toString()}
fun String.encodeMd5():String{return printHexBinary(MessageDigest.getInstance("MD5").digest(toByteArray()))}// see more https://www.baeldung.com/sha-256-hashing-java
fun String.encodeSha256():String{// Java provides inbuilt MessageDigest class for SHA-256 hashingreturn printHexBinary(MessageDigest.getInstance("SHA-256").digest(toByteArray()))}
fun main()= runBlocking {// HttpClientEngineFactory using a Coroutine based I/O implementation
val client =HttpClient(CIO){
install(JsonFeature){
serializer =KotlinxSerializer(kotlinx.serialization.json.Json{
ignoreUnknownKeys =true
prettyPrint =true
isLenient =true})}//log all requests
install(Logging){
logger =Logger.DEFAULT
level =LogLevel.ALL
}
install(HttpCookies){// Will keep an in-memory map with all the cookies from previous requests.
storage =AcceptAllCookiesStorage()}}// try with resource kotlin way
client.use {// do auth
authorized(client){// here we have authorize
val interfaceInfo:HttpResponse= client.get("http://192.168.1.1/rci/show/interface?name=ISP")}}}private suspend fun authorized(client:HttpClient, body: suspend ()->Unit){
val unauthorizedResponse = client.get<HttpResponse>("http://192.168.1.1/auth"){ expectSuccess =false}if(unauthorizedResponse.status ==HttpStatusCode.Unauthorized){
val tokenAndRealm =KeeneticAuthHeaderValues(unauthorizedResponse.headers.asMap())
val authPostResponse = authRequest(client, tokenAndRealm, LOGIN, PASSWORD)if(authPostResponse.status ==HttpStatusCode.OK){
body()}}elseif(unauthorizedResponse.status ==HttpStatusCode.OK){
body()}}private suspend fun authRequest(
client:HttpClient,
tokenAndRealm:KeeneticAuthHeaderValues,):HttpResponse{
val authPostResponse = client.post<HttpResponse>("http://192.168.1.1/auth"){
contentType(ContentType.Application.Json)
expectSuccess =false
val md5 =(LOGIN +":"+ tokenAndRealm.xndmRealm +':'+ PASSWORD).encodeMd5()
body =UserCredentials(
login = LOGIN,
password =(tokenAndRealm.xndmChallenge + md5).encodeSha256())}return authPostResponse
}
Авторизация на NDMS с помощью curl.
in Обмен опытом
Posted
Т.к. тема с примерами кода закрыта, отправлю сюда вариант на Kotlin + Ktor (gist):