[APIv2/Vulcan] Use Wulkanowy uonet-request-signer.

This commit is contained in:
Kuba Szczodrzyński 2019-11-01 21:31:26 +01:00
parent 0b211c4f12
commit e3bb607303
5 changed files with 30 additions and 73 deletions

View File

@ -160,6 +160,8 @@ dependencies {
//implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1' //implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1'
implementation "org.redundent:kotlin-xml-builder:1.5.3" implementation "org.redundent:kotlin-xml-builder:1.5.3"
implementation "io.github.wulkanowy:signer-android:0.1.0"
} }
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -4,17 +4,18 @@
package pl.szczodrzynski.edziennik.api.v2.vulcan.data package pl.szczodrzynski.edziennik.api.v2.vulcan.data
import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import im.wangchao.mhttp.Request import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler import im.wangchao.mhttp.callback.JsonCallbackHandler
import io.github.wulkanowy.signer.android.signContent
import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.api.v2.models.ApiError
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.util.* import java.util.*
@ -26,17 +27,20 @@ open class VulcanApi(open val data: DataVulcan) {
val profileId val profileId
get() = data.profile?.id ?: -1 get() = data.profile?.id ?: -1
val profile fun apiGet(
get() = data.profile tag: String,
endpoint: String,
fun apiGet(tag: String, endpoint: String, method: Int = POST, payload: JsonObject? = null, method: Int = POST,
baseUrl: Boolean = false, onSuccess: (json: JsonObject, response: Response?) -> Unit) { parameters: Map<String, Any> = emptyMap(),
val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint" baseUrl: Boolean = false,
onSuccess: (json: JsonObject, response: Response?) -> Unit
) {
val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}/$endpoint"
d(tag, "Request: Vulcan/Api - $url") d(tag, "Request: Vulcan/Api - $url")
if (data.teamList.size() == 0) { if (data.teamList.size() == 0) {
profile?.getStudentData("studentClassName", null)?.also { name -> data.profile?.getStudentData("studentClassName", null)?.also { name ->
val id = Utils.crc16(name.toByteArray()).toLong() val id = Utils.crc16(name.toByteArray()).toLong()
val teamObject = Team( val teamObject = Team(
@ -51,28 +55,24 @@ open class VulcanApi(open val data: DataVulcan) {
} }
} }
val startDate = when (profile?.empty) {
true -> profile?.getSemesterStart(profile?.currentSemester ?: 1)?.stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
}
val endDate = profile?.getSemesterEnd(profile?.currentSemester ?: 1)?.stringY_m_d
val finalPayload = JsonObject() val finalPayload = JsonObject()
finalPayload.addProperty("IdUczen", data.studentId) parameters.map { (name, value) ->
finalPayload.addProperty("IdOkresKlasyfikacyjny", data.studentSemesterId) when (value) {
finalPayload.addProperty("IdOddzial", data.studentClassId) is JsonObject -> finalPayload.add(name, value)
finalPayload.addProperty("DataPoczatkowa", startDate) is JsonArray -> finalPayload.add(name, value)
finalPayload.addProperty("DataKoncowa", endDate) is String -> finalPayload.addProperty(name, value)
is Int -> finalPayload.addProperty(name, value)
is Long -> finalPayload.addProperty(name, value)
is Float -> finalPayload.addProperty(name, value)
is Char -> finalPayload.addProperty(name, value)
}
}
finalPayload.addProperty("RemoteMobileTimeKey", System.currentTimeMillis() / 1000) finalPayload.addProperty("RemoteMobileTimeKey", System.currentTimeMillis() / 1000)
finalPayload.addProperty("TimeKey", System.currentTimeMillis() / 1000 - 1) finalPayload.addProperty("TimeKey", System.currentTimeMillis() / 1000 - 1)
finalPayload.addProperty("RequestId", UUID.randomUUID().toString()) finalPayload.addProperty("RequestId", UUID.randomUUID().toString())
finalPayload.addProperty("RemoteMobileAppVersion", VULCAN_API_APP_VERSION) finalPayload.addProperty("RemoteMobileAppVersion", VULCAN_API_APP_VERSION)
finalPayload.addProperty("RemoteMobileAppName", VULCAN_API_APP_NAME) finalPayload.addProperty("RemoteMobileAppName", VULCAN_API_APP_NAME)
payload?.keySet()?.forEach {
finalPayload.add(it, payload.get(it))
}
val callback = object : JsonCallbackHandler() { val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) { override fun onSuccess(json: JsonObject?, response: Response?) {
if (json == null && response?.parserErrorBody == null) { if (json == null && response?.parserErrorBody == null) {
@ -86,10 +86,11 @@ open class VulcanApi(open val data: DataVulcan) {
503 -> ERROR_VULCAN_API_MAINTENANCE 503 -> ERROR_VULCAN_API_MAINTENANCE
400 -> ERROR_VULCAN_API_BAD_REQUEST 400 -> ERROR_VULCAN_API_BAD_REQUEST
else -> ERROR_VULCAN_API_OTHER else -> ERROR_VULCAN_API_OTHER
}.let { }.let { errorCode ->
data.error(ApiError(tag, EXCEPTION_VULCAN_API_REQUEST) data.error(ApiError(tag, errorCode)
.withResponse(response) .withResponse(response)
.withApiResponse(json?.toString() ?: response?.parserErrorBody)) .withApiResponse(json?.toString() ?: response?.parserErrorBody))
return
} }
} }

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) Wulkanowy kiedyś tam.
*/
package pl.szczodrzynski.edziennik.api.v2.vulcan.data
import android.util.Base64
import java.io.ByteArrayInputStream
import java.security.KeyFactory
import java.security.KeyStore
import java.security.PrivateKey
import java.security.Signature
import java.security.spec.PKCS8EncodedKeySpec
fun signContent(password: String, certificate: String?, content: String): String {
val keystore = KeyStore.getInstance("pkcs12").apply {
load(ByteArrayInputStream(Base64.decode(certificate, Base64.DEFAULT)), password.toCharArray())
}
val signature = Signature.getInstance("SHA1WithRSA").apply {
initSign(keystore.getKey("LoginCert", password.toCharArray()) as PrivateKey)
update(content.toByteArray())
}
return Base64.encodeToString(signature.sign(), Base64.NO_WRAP)
}
fun signContent(privateKey: String, content: String): String {
val key = PKCS8EncodedKeySpec(Base64.decode(privateKey, Base64.DEFAULT)).let {
KeyFactory.getInstance("RSA").generatePrivate(it)
}
val signature = Signature.getInstance("SHA1WithRSA").apply {
initSign(key)
update(content.toByteArray())
}
return Base64.encodeToString(signature.sign(), Base64.NO_WRAP)
}
fun getPrivateKeyFromCert(password: String, certificate: String): String {
val keystore = KeyStore.getInstance("pkcs12").apply {
load(ByteArrayInputStream(Base64.decode(certificate, Base64.DEFAULT)), password.toCharArray())
}
val keyFactory = KeyFactory.getInstance("RSA")
val keySpec = keyFactory.getKeySpec(
keystore.getKey("LoginCert", password.toCharArray()) as PrivateKey,
PKCS8EncodedKeySpec::class.java
)
return Base64.encodeToString(keySpec.encoded, Base64.NO_WRAP)
}

View File

@ -9,10 +9,10 @@ import com.google.gson.JsonObject
import im.wangchao.mhttp.Request import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler import im.wangchao.mhttp.callback.JsonCallbackHandler
import io.github.wulkanowy.signer.android.getPrivateKeyFromCert
import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.api.v2.models.ApiError
import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.getPrivateKeyFromCert
import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.currentTimeUnix
import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.getString

View File

@ -81,6 +81,7 @@ allprojects {
jcenter() jcenter()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
maven { url "https://kotlin.bintray.com/kotlinx/" } maven { url "https://kotlin.bintray.com/kotlinx/" }
maven { url "https://dl.bintray.com/wulkanowy/wulkanowy" }
} }
} }