refactor(util): 重构 MFAUtil 并优化相关服务
All checks were successful
Sakura-Miki-build / Automatic-Packaging (push) Successful in 4m48s

- 移除了 DownloadUtil 中的注释代码
- 修改了 MFAGenerateService 中的 MFA 验证码生成逻辑
- 重构了 MFAUtil 类,增加了默认步长的 generate 方法
- 更新了 JsonUtil,添加了对象与 JSON 字符串互转的扩展函数
- 在 pom.xml 中添加了 hutool-http 依赖
This commit is contained in:
Grand-cocoa 2025-08-20 17:16:02 +08:00
parent d3931b215c
commit 0374346f6a
5 changed files with 53 additions and 34 deletions

View File

@ -163,6 +163,11 @@
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>5.8.31</version>
</dependency>
</dependencies>
<build>

View File

@ -47,12 +47,6 @@ class DownloadUtil {
return this.newCall(Request.Builder()
.url(url)
.method(method, body)
//// .addHeader("Content-Type", "application/json")
//// .addHeader("Authorization", "Bearer $APIKEY")
// .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
// .addHeader("Accept", "*/*")
// .addHeader("Host", "api.github.com")
// .addHeader("Connection", "keep-alive")
.build()).execute()
}
}

View File

@ -57,7 +57,7 @@ class MFAGenerateService : Service<FriendMessageEvent> {
event.send("您还没有绑定默认MFA使用 #mfa bind default <secret> 绑定默认MFA")
return
}
event.send(MFAUtil.generate(mfa.secret, 30))
event.send(MFAUtil.generate(mfa.secret))
return
}
if (command.size == 2){
@ -70,7 +70,7 @@ class MFAGenerateService : Service<FriendMessageEvent> {
event.send("您还没有绑定${command[1]} MFA使用 #mfa bind ${command[1]} <secret> 绑定${command[1]} MFA")
return
}
event.send(MFAUtil.generate(mfa.secret, 30))
event.send(MFAUtil.generate(mfa.secret))
return
}
}

View File

@ -7,7 +7,15 @@ import com.fasterxml.jackson.databind.ObjectMapper
* @author Kane
* @since 2025/3/24 16:10
*/
private val OBJECT_MAPPER = ObjectMapper()
val OBJECT_MAPPER = ObjectMapper()
fun parse(json: String): Dict {
return OBJECT_MAPPER.readValue(json, OBJECT_MAPPER.typeFactory.constructType(Dict::class.java))
}
inline fun <reified T : Any> T.toJson(): String {
return OBJECT_MAPPER.writeValueAsString(this)
}
inline fun <reified T : Any> T.ofJson(json: String): T{
return OBJECT_MAPPER.readValue(json, T::class.java)
}

View File

@ -11,41 +11,53 @@ import kotlin.math.pow
* @since 2025/3/18 16:01
*/
class MFAUtil {
companion object{
companion object {
private const val ALGORITHM = "HmacSHA1"
private val mac = Mac.getInstance(ALGORITHM)
private const val CODE_DIGITS = 6
private const val CODE_MODULUS = 10.0
/**
* 生成 MFA 验证码
*/
fun generate(key: String, step: Int): String {
val data = ByteArray(8)
var value = System.currentTimeMillis() / 1000 / step
run {
var i = 8
while (i-- > 0) {
return try {
val data = ByteArray(8)
var value = System.currentTimeMillis() / 1000 / step
for (i in 7 downTo 0) {
data[i] = value.toByte()
value = value ushr 8
}
val decodedKey = Base32.decode(key)
val signKey = SecretKeySpec(decodedKey, ALGORITHM)
mac.init(signKey)
val hash = mac.doFinal(data)
val offset = hash[hash.size - 1].toInt() and 0xF
var truncatedHash: Long = 0
for (i in 0..3) {
truncatedHash = truncatedHash shl 8
truncatedHash = truncatedHash or (hash[offset + i].toInt() and 0xFF).toLong()
}
truncatedHash = truncatedHash and 0x7FFFFFFFL
truncatedHash %= CODE_MODULUS.pow(CODE_DIGITS).toLong()
"%0${CODE_DIGITS}d".format(truncatedHash)
} catch (e: Exception) {
throw RuntimeException("Failed to generate MFA code", e)
}
val decodedKey = Base32.decode(key)
val signKey = SecretKeySpec(decodedKey, ALGORITHM)
mac.init(signKey)
val hash = mac.doFinal(data)
println(hash.contentToString())
val offset = hash[hash.size - 1].toInt() and 0xF
var truncatedHash: Long = 0
for (i in 0..3) {
truncatedHash = truncatedHash shl 8
truncatedHash = truncatedHash or (hash[offset + i].toInt() and 0xFF).toLong()
}
truncatedHash = truncatedHash and 0x7FFFFFFFL
truncatedHash %= 10.0.pow(6.0).toLong()
return String.format("%0" + 6 + "d", truncatedHash)
}
/**
* 生成默认步长30 MFA 验证码
*
* @param key Base32编码的密钥
* @return 6位数字验证码
*/
fun generate(key: String): String = generate(key, 30)
}
}