Перейти к содержанию

Вопрос

Опубликовано

Добрый день!

Купил keenetic air, стоит ndms 3.5.1 . 

Требуется сделать реконнект, например с помощью curl.

Ни в какую не получается авторизоваться, шлю {"login":"admin","password":"md5($password)"} на /auth , в чем проблема авторизации, непонятно. Защита яваскрипт какая-то?

Есть готовые решения у кого-нибудь?

Спасибо!

Рекомендуемые сообщения

  • 0
Опубликовано
1 час назад, Roundik сказал:

Добрый день!

Купил keenetic air, стоит ndms 3.5.1 . 

Требуется сделать реконнект, например с помощью curl.

Ни в какую не получается авторизоваться, шлю {"login":"admin","password":"md5($password)"} на /auth , в чем проблема авторизации, непонятно. Защита яваскрипт какая-то?

Есть готовые решения у кого-нибудь?

Спасибо!

 

  • 0
Опубликовано

Т.к. тема с примерами кода закрыта, отправлю сюда вариант на Kotlin + Ktor (gist):

import kotlinx.serialization.Serializable
import io.ktor.http.*
import java.security.MessageDigest
import 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
  
private const val LOGIN = "login"
private const val PASSWORD = "password"    
  
data class KeeneticAuthHeaderValues(
    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 class UserCredentials(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 hexadecimal
private 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 hashing
    return 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()
        }
    } else if(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
}

 

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...

Важная информация

На этом сайте используются файлы cookie. Нажимая "Я принимаю" или продолжая просмотр сайта, вы разрешаете их использование: Политика конфиденциальности.