refactor(util): 重构 MFAUtil 并优化相关服务
All checks were successful
Sakura-Miki-build / Automatic-Packaging (push) Successful in 4m48s
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:
parent
d3931b215c
commit
0374346f6a
5
pom.xml
5
pom.xml
@ -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>
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user