Skip to content

Commit

Permalink
feat: 去除单点登录限制,修复签发新refreshToken使用旧过期时间的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
dragove committed Oct 28, 2024
1 parent fb8bf95 commit 8d19c08
Show file tree
Hide file tree
Showing 5 changed files with 3 additions and 56 deletions.
4 changes: 0 additions & 4 deletions src/main/kotlin/plus/maa/backend/config/external/Jwt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,4 @@ data class Jwt(
* JwtToken的加密密钥
*/
var secret: String = "",
/**
* Jwt 最大同时登录设备数
*/
var maxLogin: Int = 1,
)
24 changes: 2 additions & 22 deletions src/main/kotlin/plus/maa/backend/service/UserService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import org.springframework.data.repository.findByIdOrNull
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import plus.maa.backend.common.MaaStatusCode
import plus.maa.backend.config.external.MaaCopilotProperties
import plus.maa.backend.controller.request.user.LoginDTO
import plus.maa.backend.controller.request.user.PasswordResetDTO
import plus.maa.backend.controller.request.user.RegisterDTO
Expand All @@ -19,7 +18,6 @@ import plus.maa.backend.repository.entity.MaaUser
import plus.maa.backend.service.jwt.JwtExpiredException
import plus.maa.backend.service.jwt.JwtInvalidException
import plus.maa.backend.service.jwt.JwtService
import java.util.UUID

/**
* @author AnselYuki
Expand All @@ -31,7 +29,6 @@ class UserService(
private val passwordEncoder: PasswordEncoder,
private val userDetailService: UserDetailServiceImpl,
private val jwtService: JwtService,
private val properties: MaaCopilotProperties,
) {
/**
* 登录方法
Expand All @@ -49,15 +46,9 @@ class UserService(
throw MaaResultException(MaaStatusCode.MAA_USER_NOT_ENABLED)
}

val jwtId = UUID.randomUUID().toString()
val jwtIds = user.refreshJwtIds
jwtIds.add(jwtId)
while (jwtIds.size > properties.jwt.maxLogin) jwtIds.removeAt(0)
userRepository.save(user)

val authorities = userDetailService.collectAuthoritiesFor(user)
val authToken = jwtService.issueAuthToken(user.userId!!, null, authorities)
val refreshToken = jwtService.issueRefreshToken(user.userId, jwtId)
val refreshToken = jwtService.issueRefreshToken(user.userId, null)

return MaaLoginRsp(
authToken.value,
Expand Down Expand Up @@ -144,18 +135,7 @@ class UserService(

val userId = old.subject
val user = userRepository.findById(userId).orElseThrow()

val refreshJwtIds = user.refreshJwtIds
val idIndex = refreshJwtIds.indexOf(old.jwtId)
if (idIndex < 0) throw MaaResultException(401, "invalid token")

val jwtId = UUID.randomUUID().toString()
refreshJwtIds[idIndex] = jwtId

userRepository.save(user)

val refreshToken = jwtService.newRefreshToken(old, jwtId)

val refreshToken = jwtService.issueRefreshToken(userId, null)
val authorities = userDetailService.collectAuthoritiesFor(user)
val authToken = jwtService.issueAuthToken(userId, null, authorities)

Expand Down
12 changes: 0 additions & 12 deletions src/main/kotlin/plus/maa/backend/service/jwt/JwtService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,6 @@ class JwtService(properties: MaaCopilotProperties) {
return JwtRefreshToken(subject, jwtId, now, expireAt, now, key)
}

/**
* 产生新的 RefreshToken. 新的 token 除了签发和生效时间、 id 不同外,其余属性均继承自原来的 token.
* 一般情况下, RefreshToken 应结合数据库使用以避免陷入无法撤销的窘境
*
* @param old 原 token
* @return 新的 RefreshToken
*/
fun newRefreshToken(old: JwtRefreshToken, jwtId: String?): JwtRefreshToken {
val now = Instant.now()
return JwtRefreshToken(old.subject, jwtId, now, old.expiresAt, now, key)
}

/**
* 验证并解析为 RefreshToken. 该方法为 stateless 的验证。
*
Expand Down
1 change: 0 additions & 1 deletion src/main/resources/application-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ maa-copilot:
expire: 21600
# JwtToken的加密密钥
secret: $I_Am_The_Bone_Of_My_Sword!Steel_Is_My_Body_And_Fire_Is_My_Blood!$
max-login: 1
github:
# GitHub api token
token: github_pat_xxx
Expand Down
18 changes: 1 addition & 17 deletions src/test/kotlin/plus/maa/backend/service/jwt/JwtServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,6 @@ class JwtServiceTest {
check(parsedToken.isAuthenticated)
}

@Test
@Throws(JwtExpiredException::class, JwtInvalidException::class)
fun refreshTokenCodec() {
val service = createService()

val subject = "some user id"
val origin = service.issueRefreshToken(subject, null)

val parsedToken = service.verifyAndParseRefreshToken(origin.value)
check(subject == parsedToken.subject)
val newToken = service.newRefreshToken(parsedToken, null)
check(!newToken.issuedAt.isBefore(parsedToken.issuedAt))
check(!newToken.notBefore.isBefore(parsedToken.notBefore))
check(newToken.expiresAt == parsedToken.expiresAt)
}

@Test
fun wrongTypeParseShouldFail() {
val service = createService()
Expand All @@ -58,4 +42,4 @@ class JwtServiceTest {
service.verifyAndParseAuthToken(refreshToken.value)
}
}
}
}

0 comments on commit 8d19c08

Please sign in to comment.