-
Notifications
You must be signed in to change notification settings - Fork 342
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
472 additions
and
853 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 168 additions & 0 deletions
168
mirai-api-http/src/test/kotlin/integration/auth/HttpAuthTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package integration.auth | ||
|
||
import io.ktor.client.call.* | ||
import io.ktor.client.request.* | ||
import net.mamoe.mirai.api.http.adapter.common.StateCode | ||
import net.mamoe.mirai.api.http.adapter.internal.consts.Paths | ||
import net.mamoe.mirai.api.http.adapter.internal.dto.* | ||
import net.mamoe.mirai.api.http.adapter.internal.serializer.jsonElementParseOrNull | ||
import net.mamoe.mirai.api.http.context.MahContext | ||
import framework.MahApplicationTestBuilder | ||
import framework.testMahApplication | ||
import framework.SetupMockBot | ||
import integration.withSession | ||
import org.junit.jupiter.api.extension.ExtendWith | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertNotNull | ||
|
||
/** | ||
* 测试 Session 在不同情况下的正确性 | ||
*/ | ||
@ExtendWith(SetupMockBot::class) | ||
class HttpAuthTest { | ||
|
||
private val verifyKey = "session test" | ||
private val pathsVerify = Paths.httpPath("verify") | ||
private val pathsBind = Paths.httpPath("bind") | ||
|
||
/** | ||
* 测试单session需要认证 | ||
*/ | ||
@Test | ||
fun testSingleSessionOnHttp() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = true, | ||
singleMode = true, | ||
) { | ||
installHttpAdapter() | ||
|
||
getSessionInfoAndExpect(null, StateCode.NotVerifySession) | ||
|
||
postJsonData<StateCode>(pathsVerify, VerifyDTO("wrong $verifyKey")).also { | ||
assertEquals(StateCode.AuthKeyFail.code, it.code) | ||
} | ||
|
||
postJsonData<VerifyRetDTO>(pathsVerify, VerifyDTO(verifyKey)).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
} | ||
|
||
getSessionInfoAndExpect(null) | ||
} | ||
|
||
/** | ||
* 测试无需认证的单 Session 模式 | ||
*/ | ||
@Test | ||
fun testSingleSessionOnHttpWithoutAuth() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = false, | ||
singleMode = true, | ||
) { | ||
installHttpAdapter() | ||
|
||
// 无需认证的单例 session 模式可以直接访问 | ||
getSessionInfoAndExpect(null) | ||
|
||
postJsonData<VerifyRetDTO>(pathsVerify, VerifyDTO(verifyKey)).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
} | ||
|
||
postJsonData<VerifyRetDTO>(pathsVerify, VerifyDTO("wrong $verifyKey")).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
} | ||
|
||
getSessionInfoAndExpect(null) | ||
} | ||
|
||
/** | ||
* 测试需认证的通常 Session 模式 | ||
*/ | ||
@Test | ||
fun testAuthNormalSessionOnHttp() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = true, | ||
singleMode = false, | ||
) { | ||
installHttpAdapter() | ||
|
||
getSessionInfoAndExpect("nonexistent session", StateCode.IllegalSession) | ||
|
||
postJsonData<StateCode>(pathsVerify, VerifyDTO("wrong $verifyKey")).also { | ||
assertEquals(StateCode.AuthKeyFail.code, it.code) | ||
} | ||
|
||
val verifyRet = postJsonData<VerifyRetDTO>(pathsVerify, VerifyDTO(verifyKey)).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
assertNotNull(it.session) | ||
} | ||
|
||
// 认证但未绑定 | ||
getSessionInfoAndExpect(verifyRet.session, errorState = StateCode.NotVerifySession) | ||
|
||
// bind | ||
postJsonData<StateCode>(pathsBind, BindDTO(SetupMockBot.ID)).also { | ||
assertEquals(StateCode.IllegalSession.code, it.code) | ||
} | ||
|
||
// bind with session | ||
postJsonData<StateCode>(pathsBind, BindDTO(SetupMockBot.ID).withSession(verifyRet.session)).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
} | ||
|
||
getSessionInfoAndExpect(verifyRet.session) | ||
} | ||
|
||
@Test | ||
fun testAuthNormalSessionOnHttpWithAuth() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = false, | ||
singleMode = false, | ||
) { | ||
installHttpAdapter() | ||
|
||
// 非单例 session 模式下,出现找不到 session 异常 | ||
getSessionInfoAndExpect("nonexistent session", StateCode.IllegalSession) | ||
|
||
// 无需认证key,但仍需要通过认证接口获取 session | ||
val verifyRet = postJsonData<VerifyRetDTO>(pathsVerify, VerifyDTO("Arbitrary $verifyKey")).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
assertNotNull(it.session) | ||
} | ||
|
||
// 认证但未绑定 | ||
getSessionInfoAndExpect(verifyRet.session, errorState = StateCode.NotVerifySession) | ||
|
||
// use session to bind | ||
postJsonData<StateCode>(pathsBind, BindDTO(SetupMockBot.ID).withSession(verifyRet.session)).also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
} | ||
|
||
getSessionInfoAndExpect(verifyRet.session) | ||
} | ||
|
||
private suspend fun MahApplicationTestBuilder.getSessionInfoAndExpect( | ||
sessionKey: String?, | ||
errorState: StateCode? = null | ||
) { | ||
if (errorState == null) { | ||
// expect success | ||
val resp = client.get(Paths.sessionInfo) { | ||
parameter("sessionKey", sessionKey) | ||
}.body<ElementResult>() | ||
|
||
val ret = resp.data.jsonElementParseOrNull<SessionDTO>() | ||
|
||
assertNotNull(ret) | ||
assertEquals(sessionKey ?: MahContext.SINGLE_SESSION_KEY, ret.sessionKey) | ||
assertEquals(SetupMockBot.ID, ret.qq.id) | ||
} else { | ||
val ret = client.get(Paths.sessionInfo) { | ||
parameter("sessionKey", sessionKey) | ||
}.body<StateCode>() | ||
|
||
assertNotNull(ret) | ||
assertEquals(errorState.code, ret.code) | ||
} | ||
} | ||
} |
146 changes: 146 additions & 0 deletions
146
mirai-api-http/src/test/kotlin/integration/auth/WebSocketAuthTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package integration.auth | ||
|
||
import framework.SetupMockBot | ||
import framework.testMahApplication | ||
import integration.receiveDTO | ||
import integration.withSession | ||
import io.ktor.client.plugins.websocket.* | ||
import net.mamoe.mirai.api.http.adapter.common.StateCode | ||
import net.mamoe.mirai.api.http.adapter.internal.consts.Paths | ||
import net.mamoe.mirai.api.http.adapter.internal.dto.BindDTO | ||
import net.mamoe.mirai.api.http.adapter.internal.dto.VerifyDTO | ||
import net.mamoe.mirai.api.http.adapter.internal.dto.VerifyRetDTO | ||
import net.mamoe.mirai.api.http.context.MahContext | ||
import org.junit.jupiter.api.extension.ExtendWith | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertNotEquals | ||
|
||
@ExtendWith(SetupMockBot::class) | ||
class WebSocketAuthTest { | ||
|
||
private val verifyKey = "session test" | ||
private val verifyPath = Paths.httpPath("verify") | ||
private val bindPath = Paths.httpPath("bind") | ||
|
||
/** | ||
* 单例 session 模式下建立 ws 链接 | ||
*/ | ||
@Test | ||
fun testSingleSessionOnWs() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = true, | ||
singleMode = true, | ||
debug = false, | ||
) { | ||
installWsAdapter() | ||
|
||
client.ws("/all?verifyKey=wrongVerifyKey") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.AuthKeyFail.code, it.code) | ||
} | ||
} | ||
|
||
client.ws("/all?verifyKey=$verifyKey") { | ||
receiveDTO<VerifyRetDTO>().also { | ||
assertEquals(MahContext.SINGLE_SESSION_KEY, it.session) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 单例 session 模式下无需验证建立链接, 这是最宽松的验证, 完全没有安全性 | ||
*/ | ||
@Test | ||
fun testSingleSessionONWsWithoutAuth() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = false, | ||
singleMode = true, | ||
debug = false, | ||
) { | ||
installWsAdapter() | ||
|
||
client.ws("/all") { | ||
receiveDTO<VerifyRetDTO>().also { | ||
assertEquals(MahContext.SINGLE_SESSION_KEY, it.session) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 测试需要认证的 session 模式建立链接, 这是最常用的方案 | ||
*/ | ||
@Test | ||
fun testAuthNormalSessionOnWs() = testMahApplication( | ||
verifyKey = verifyKey, | ||
enableVerify = true, | ||
singleMode = false, | ||
debug = false, | ||
) { | ||
installHttpAdapter() | ||
installWsAdapter() | ||
|
||
// 错误 verify key | ||
client.ws("/all?verifyKey=wrongVerifyKey") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.AuthKeyFail.code, it.code) | ||
} | ||
} | ||
|
||
// 不绑定账号 | ||
client.ws("/all?verifyKey=$verifyKey") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.InvalidParameter.code, it.code) | ||
} | ||
} | ||
|
||
// 无法绑定账号(绑定错误账号) | ||
client.ws("/all?verifyKey=$verifyKey&qq=${SetupMockBot.ID + 1}") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.NoBot.code, it.code) | ||
} | ||
} | ||
|
||
// 通过已有 session 绑定 | ||
|
||
// 通过 http 创建一个session | ||
val session = postJsonData<VerifyRetDTO>(verifyPath, VerifyDTO(verifyKey)).session | ||
|
||
// 通过 ws 绑定错误 session | ||
client.ws("/all?verifyKey=$verifyKey&sessionKey=wrong$session") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.IllegalSession.code, it.code) | ||
} | ||
} | ||
|
||
// 通过 ws 绑定已有未认证 session | ||
client.ws("/all?verifyKey=$verifyKey&sessionKey=$session") { | ||
receiveDTO<StateCode>().also { | ||
assertEquals(StateCode.NotVerifySession.code, it.code) | ||
} | ||
} | ||
|
||
// 通过 http 认证 session | ||
postJsonData<StateCode>(bindPath, BindDTO(SetupMockBot.ID).withSession(session)) | ||
|
||
var ret: VerifyRetDTO? = null | ||
// 通过 ws 绑定已有已认证 session | ||
client.ws("/all?verifyKey=$verifyKey&sessionKey=$session") { | ||
receiveDTO<VerifyRetDTO>().also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
assertNotEquals(MahContext.SINGLE_SESSION_KEY, it.session) | ||
ret = it | ||
} | ||
} | ||
|
||
// 通过 ws 创建新 session 并绑定 | ||
client.ws("/all?verifyKey=$verifyKey&qq=${SetupMockBot.ID}") { | ||
receiveDTO<VerifyRetDTO>().also { | ||
assertEquals(StateCode.Success.code, it.code) | ||
assertNotEquals(MahContext.SINGLE_SESSION_KEY, it.session) | ||
// not same session | ||
assertNotEquals(ret?.session, it.session) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.