Optimize authentication api
This commit is contained in:
@@ -14,6 +14,7 @@ enum class ResponseCode(val code: Int) {
|
|||||||
SYSTEM_REQUEST_ILLEGAL(BusinessCode.SYSTEM, 52),
|
SYSTEM_REQUEST_ILLEGAL(BusinessCode.SYSTEM, 52),
|
||||||
SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 53),
|
SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 53),
|
||||||
SYSTEM_INVALID_CAPTCHA_CODE(BusinessCode.SYSTEM, 54),
|
SYSTEM_INVALID_CAPTCHA_CODE(BusinessCode.SYSTEM, 54),
|
||||||
|
SYSTEM_REQUEST_TOO_FREQUENT(BusinessCode.SYSTEM, 55),
|
||||||
|
|
||||||
PERMISSION_LOGIN_SUCCESS(BusinessCode.PERMISSION, 0),
|
PERMISSION_LOGIN_SUCCESS(BusinessCode.PERMISSION, 0),
|
||||||
PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1),
|
PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1),
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package top.fatweb.oxygen.api.exception
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request too frequent exception
|
||||||
|
*
|
||||||
|
* @author FatttSnake, fatttsnake@gmail.com
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class RequestTooFrequent: RuntimeException("Request too frequent")
|
||||||
@@ -58,6 +58,11 @@ class ExceptionHandler {
|
|||||||
ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null)
|
ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is RequestTooFrequent -> {
|
||||||
|
logger.debug(e.localizedMessage, e)
|
||||||
|
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_TOO_FREQUENT, e.localizedMessage, null)
|
||||||
|
}
|
||||||
|
|
||||||
is InsufficientAuthenticationException -> {
|
is InsufficientAuthenticationException -> {
|
||||||
logger.debug(e.localizedMessage, e)
|
logger.debug(e.localizedMessage, e)
|
||||||
ResponseResult.fail(ResponseCode.PERMISSION_UNAUTHORIZED, e.localizedMessage, null)
|
ResponseResult.fail(ResponseCode.PERMISSION_UNAUTHORIZED, e.localizedMessage, null)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package top.fatweb.oxygen.api.param
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema
|
||||||
|
import jakarta.validation.constraints.NotBlank
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captcha code parameter
|
||||||
|
*
|
||||||
|
* @author FatttSnake, fatttsnake@gmail.com
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
open class CaptchaCodeParam {
|
||||||
|
/**
|
||||||
|
* Captcha code
|
||||||
|
*
|
||||||
|
* @author FatttSnake, fatttsnake@gmail.com
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
@Schema(description = "验证码", required = true)
|
||||||
|
@field:NotBlank(message = "Captcha code can not be blank")
|
||||||
|
var captchaCode: String? = null
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package top.fatweb.oxygen.api.param.permission
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema
|
import io.swagger.v3.oas.annotations.media.Schema
|
||||||
import jakarta.validation.constraints.NotBlank
|
import jakarta.validation.constraints.NotBlank
|
||||||
import jakarta.validation.constraints.Pattern
|
import jakarta.validation.constraints.Pattern
|
||||||
|
import top.fatweb.oxygen.api.param.CaptchaCodeParam
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forget password parameters
|
* Forget password parameters
|
||||||
@@ -22,4 +23,4 @@ data class ForgetParam(
|
|||||||
@field:NotBlank(message = "Email can not be blank")
|
@field:NotBlank(message = "Email can not be blank")
|
||||||
@field:Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
|
@field:Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
|
||||||
val email: String?
|
val email: String?
|
||||||
)
|
) : CaptchaCodeParam()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package top.fatweb.oxygen.api.param.permission
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema
|
import io.swagger.v3.oas.annotations.media.Schema
|
||||||
import jakarta.validation.constraints.NotBlank
|
import jakarta.validation.constraints.NotBlank
|
||||||
|
import top.fatweb.oxygen.api.param.CaptchaCodeParam
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login parameters
|
* Login parameters
|
||||||
@@ -29,15 +30,5 @@ data class LoginParam(
|
|||||||
*/
|
*/
|
||||||
@Schema(description = "密码", required = true)
|
@Schema(description = "密码", required = true)
|
||||||
@field:NotBlank(message = "Password can not be blank")
|
@field:NotBlank(message = "Password can not be blank")
|
||||||
val password: String?,
|
val password: String?
|
||||||
|
) : CaptchaCodeParam()
|
||||||
/**
|
|
||||||
* Captcha code
|
|
||||||
*
|
|
||||||
* @author FatttSnake, fatttsnake@gmail.com
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
@Schema(description = "验证码", required = true)
|
|
||||||
@field:NotBlank(message = "Captcha code can not be blank")
|
|
||||||
val captchaCode: String?
|
|
||||||
)
|
|
||||||
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema
|
|||||||
import jakarta.validation.constraints.NotBlank
|
import jakarta.validation.constraints.NotBlank
|
||||||
import jakarta.validation.constraints.Pattern
|
import jakarta.validation.constraints.Pattern
|
||||||
import jakarta.validation.constraints.Size
|
import jakarta.validation.constraints.Size
|
||||||
|
import top.fatweb.oxygen.api.param.CaptchaCodeParam
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register parameters
|
* Register parameters
|
||||||
@@ -45,4 +46,4 @@ data class RegisterParam(
|
|||||||
@field:NotBlank(message = "Password can not be blank")
|
@field:NotBlank(message = "Password can not be blank")
|
||||||
@field:Size(min = 10, max = 30)
|
@field:Size(min = 10, max = 30)
|
||||||
val password: String?
|
val password: String?
|
||||||
)
|
) : CaptchaCodeParam()
|
||||||
@@ -3,6 +3,7 @@ package top.fatweb.oxygen.api.param.permission
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema
|
import io.swagger.v3.oas.annotations.media.Schema
|
||||||
import jakarta.validation.constraints.NotBlank
|
import jakarta.validation.constraints.NotBlank
|
||||||
import jakarta.validation.constraints.Size
|
import jakarta.validation.constraints.Size
|
||||||
|
import top.fatweb.oxygen.api.param.CaptchaCodeParam
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve password parameters
|
* Retrieve password parameters
|
||||||
@@ -32,4 +33,4 @@ data class RetrieveParam(
|
|||||||
@field:NotBlank(message = "New password can not be blank")
|
@field:NotBlank(message = "New password can not be blank")
|
||||||
@field:Size(min = 10, max = 30)
|
@field:Size(min = 10, max = 30)
|
||||||
val password: String?
|
val password: String?
|
||||||
)
|
) : CaptchaCodeParam()
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ class AuthenticationServiceImpl(
|
|||||||
@EventLogRecord(EventLog.Event.REGISTER)
|
@EventLogRecord(EventLog.Event.REGISTER)
|
||||||
@Transactional
|
@Transactional
|
||||||
override fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo {
|
override fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo {
|
||||||
|
verifyCaptcha(registerParam.captchaCode!!)
|
||||||
|
|
||||||
val user = User().apply {
|
val user = User().apply {
|
||||||
username = registerParam.username
|
username = registerParam.username
|
||||||
password = passwordEncoder.encode(registerParam.password)
|
password = passwordEncoder.encode(registerParam.password)
|
||||||
@@ -98,6 +100,12 @@ class AuthenticationServiceImpl(
|
|||||||
|
|
||||||
user.verify ?: throw NoVerificationRequiredException()
|
user.verify ?: throw NoVerificationRequiredException()
|
||||||
|
|
||||||
|
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC)
|
||||||
|
.isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5))
|
||||||
|
) {
|
||||||
|
throw RequestTooFrequent()
|
||||||
|
}
|
||||||
|
|
||||||
user.verify =
|
user.verify =
|
||||||
"${
|
"${
|
||||||
LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()
|
LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()
|
||||||
@@ -110,30 +118,6 @@ class AuthenticationServiceImpl(
|
|||||||
} ?: throw AccessDeniedException("Access Denied")
|
} ?: throw AccessDeniedException("Access Denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendVerifyMail(username: String, code: String, email: String) {
|
|
||||||
val velocityContext = VelocityContext().apply {
|
|
||||||
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
|
||||||
put("appUrl", SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost"))
|
|
||||||
put("username", username)
|
|
||||||
put(
|
|
||||||
"verifyUrl",
|
|
||||||
SettingsOperator.getAppValue(BaseSettings::verifyUrl, "http://localhost/verify?code=\${verifyCode}")
|
|
||||||
.replace(
|
|
||||||
Regex("(?<=([^\\\\]))\\$\\{verifyCode}"), code
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val template = velocityEngine.getTemplate("templates/email-verify-account-cn.vm")
|
|
||||||
|
|
||||||
val stringWriter = StringWriter()
|
|
||||||
template.merge(velocityContext, stringWriter)
|
|
||||||
|
|
||||||
MailUtil.sendSimpleMail(
|
|
||||||
"验证您的账号", stringWriter.toString(), true,
|
|
||||||
email
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventLogRecord(EventLog.Event.VERIFY)
|
@EventLogRecord(EventLog.Event.VERIFY)
|
||||||
@Transactional
|
@Transactional
|
||||||
override fun verify(verifyParam: VerifyParam) {
|
override fun verify(verifyParam: VerifyParam) {
|
||||||
@@ -161,8 +145,19 @@ class AuthenticationServiceImpl(
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
override fun forget(request: HttpServletRequest, forgetParam: ForgetParam) {
|
override fun forget(request: HttpServletRequest, forgetParam: ForgetParam) {
|
||||||
|
verifyCaptcha(forgetParam.captchaCode!!)
|
||||||
|
|
||||||
val user = userService.getUserWithPowerByAccount(forgetParam.email!!)
|
val user = userService.getUserWithPowerByAccount(forgetParam.email!!)
|
||||||
user ?: let { throw UserNotFoundException() }
|
user ?: let { throw UserNotFoundException() }
|
||||||
|
|
||||||
|
user.forget?.let {
|
||||||
|
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(it.split("-").first().toLong()), ZoneOffset.UTC)
|
||||||
|
.isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5))
|
||||||
|
) {
|
||||||
|
throw RequestTooFrequent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val code = "${
|
val code = "${
|
||||||
LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()
|
LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()
|
||||||
}-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}"
|
}-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}"
|
||||||
@@ -170,6 +165,95 @@ class AuthenticationServiceImpl(
|
|||||||
sendRetrieveMail(user.username!!, request.remoteAddr, code, forgetParam.email)
|
sendRetrieveMail(user.username!!, request.remoteAddr, code, forgetParam.email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
override fun retrieve(request: HttpServletRequest, retrieveParam: RetrieveParam) {
|
||||||
|
verifyCaptcha(retrieveParam.captchaCode!!)
|
||||||
|
|
||||||
|
val codeStrings = retrieveParam.code!!.split("-")
|
||||||
|
if (codeStrings.size != 16) {
|
||||||
|
throw RetrieveCodeErrorOrExpiredException()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(codeStrings.first().toLong()), ZoneOffset.UTC)
|
||||||
|
.isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2))
|
||||||
|
) {
|
||||||
|
throw RetrieveCodeErrorOrExpiredException()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw RetrieveCodeErrorOrExpiredException()
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = userService.getOne(KtQueryWrapper(User()).eq(User::forget, retrieveParam.code))
|
||||||
|
?: throw RetrieveCodeErrorOrExpiredException()
|
||||||
|
val userInfo = userInfoService.getOne(KtQueryWrapper(UserInfo()).eq(UserInfo::userId, user.id))
|
||||||
|
|
||||||
|
userService.update(
|
||||||
|
KtUpdateWrapper(User()).eq(User::id, user.id).set(User::forget, null)
|
||||||
|
.set(User::password, passwordEncoder.encode(retrieveParam.password!!))
|
||||||
|
)
|
||||||
|
|
||||||
|
WebUtil.offlineUser(redisUtil, user.id!!)
|
||||||
|
|
||||||
|
sendPasswordChangedMail(user.username!!, request.remoteAddr, userInfo!!.email!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventLogRecord(EventLog.Event.LOGIN)
|
||||||
|
override fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo {
|
||||||
|
verifyCaptcha(loginParam.captchaCode!!)
|
||||||
|
|
||||||
|
return this.login(request, loginParam.account!!, loginParam.password!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventLogRecord(EventLog.Event.LOGOUT)
|
||||||
|
override fun logout(token: String): Boolean {
|
||||||
|
val loginUser = WebUtil.getLoginUser() ?: let { throw TokenHasExpiredException() }
|
||||||
|
|
||||||
|
return redisUtil.delObject("${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renewToken(token: String): TokenVo {
|
||||||
|
val loginUser = WebUtil.getLoginUser() ?: let { throw TokenHasExpiredException() }
|
||||||
|
|
||||||
|
val oldRedisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token
|
||||||
|
redisUtil.delObject(oldRedisKey)
|
||||||
|
val jwt = JwtUtil.createJwt(WebUtil.getLoginUserId().toString())
|
||||||
|
|
||||||
|
jwt ?: let {
|
||||||
|
throw RuntimeException("Login failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
val redisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + jwt
|
||||||
|
redisUtil.setObject(
|
||||||
|
redisKey, loginUser, SecurityProperties.redisTtl, SecurityProperties.redisTtlUnit
|
||||||
|
)
|
||||||
|
|
||||||
|
return TokenVo(jwt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendVerifyMail(username: String, code: String, email: String) {
|
||||||
|
val velocityContext = VelocityContext().apply {
|
||||||
|
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
||||||
|
put("appUrl", SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost"))
|
||||||
|
put("username", username)
|
||||||
|
put(
|
||||||
|
"verifyUrl",
|
||||||
|
SettingsOperator.getAppValue(BaseSettings::verifyUrl, "http://localhost/verify?code=\${verifyCode}")
|
||||||
|
.replace(
|
||||||
|
Regex("(?<=([^\\\\]))\\$\\{verifyCode}"), code
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val template = velocityEngine.getTemplate("templates/email-verify-account-cn.vm")
|
||||||
|
|
||||||
|
val stringWriter = StringWriter()
|
||||||
|
template.merge(velocityContext, stringWriter)
|
||||||
|
|
||||||
|
MailUtil.sendSimpleMail(
|
||||||
|
"验证您的账号", stringWriter.toString(), true,
|
||||||
|
email
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun sendRetrieveMail(username: String, ip: String, code: String, email: String) {
|
private fun sendRetrieveMail(username: String, ip: String, code: String, email: String) {
|
||||||
val velocityContext = VelocityContext().apply {
|
val velocityContext = VelocityContext().apply {
|
||||||
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
||||||
@@ -198,36 +282,6 @@ class AuthenticationServiceImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
override fun retrieve(request: HttpServletRequest, retrieveParam: RetrieveParam) {
|
|
||||||
val codeStrings = retrieveParam.code!!.split("-")
|
|
||||||
if (codeStrings.size != 16) {
|
|
||||||
throw RetrieveCodeErrorOrExpiredException()
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(codeStrings.first().toLong()), ZoneOffset.UTC)
|
|
||||||
.isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2))
|
|
||||||
) {
|
|
||||||
throw RetrieveCodeErrorOrExpiredException()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw RetrieveCodeErrorOrExpiredException()
|
|
||||||
}
|
|
||||||
|
|
||||||
val user = userService.getOne(KtQueryWrapper(User()).eq(User::forget, retrieveParam.code))
|
|
||||||
?: throw RetrieveCodeErrorOrExpiredException()
|
|
||||||
val userInfo = userInfoService.getOne(KtQueryWrapper(UserInfo()).eq(UserInfo::userId, user.id))
|
|
||||||
|
|
||||||
userService.update(
|
|
||||||
KtUpdateWrapper(User()).eq(User::id, user.id).set(User::forget, null)
|
|
||||||
.set(User::password, passwordEncoder.encode(retrieveParam.password!!))
|
|
||||||
)
|
|
||||||
|
|
||||||
WebUtil.offlineUser(redisUtil, user.id!!)
|
|
||||||
|
|
||||||
sendPasswordChangedMail(user.username!!, request.remoteAddr, userInfo!!.email!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendPasswordChangedMail(username: String, ip: String, email: String) {
|
private fun sendPasswordChangedMail(username: String, ip: String, email: String) {
|
||||||
val velocityContext = VelocityContext().apply {
|
val velocityContext = VelocityContext().apply {
|
||||||
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"))
|
||||||
@@ -246,20 +300,6 @@ class AuthenticationServiceImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventLogRecord(EventLog.Event.LOGIN)
|
|
||||||
override fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo {
|
|
||||||
try {
|
|
||||||
val siteverifyResponse = turnstileApi.siteverify(loginParam.captchaCode!!)
|
|
||||||
if (!siteverifyResponse.success) {
|
|
||||||
throw InvalidCaptchaCodeException()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw InvalidCaptchaCodeException()
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.login(request, loginParam.account!!, loginParam.password!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun login(request: HttpServletRequest, account: String, password: String): LoginVo {
|
private fun login(request: HttpServletRequest, account: String, password: String): LoginVo {
|
||||||
val usernamePasswordAuthenticationToken =
|
val usernamePasswordAuthenticationToken =
|
||||||
UsernamePasswordAuthenticationToken(account, password)
|
UsernamePasswordAuthenticationToken(account, password)
|
||||||
@@ -292,29 +332,14 @@ class AuthenticationServiceImpl(
|
|||||||
return LoginVo(jwt, loginUser.user.id, loginUser.user.currentLoginTime, loginUser.user.currentLoginIp)
|
return LoginVo(jwt, loginUser.user.id, loginUser.user.currentLoginTime, loginUser.user.currentLoginIp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventLogRecord(EventLog.Event.LOGOUT)
|
private fun verifyCaptcha(captchaCode: String) {
|
||||||
override fun logout(token: String): Boolean {
|
try {
|
||||||
val loginUser = WebUtil.getLoginUser() ?: let { throw TokenHasExpiredException() }
|
val siteverifyResponse = turnstileApi.siteverify(captchaCode)
|
||||||
|
if (!siteverifyResponse.success) {
|
||||||
return redisUtil.delObject("${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token)
|
throw InvalidCaptchaCodeException()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw InvalidCaptchaCodeException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renewToken(token: String): TokenVo {
|
|
||||||
val loginUser = WebUtil.getLoginUser() ?: let { throw TokenHasExpiredException() }
|
|
||||||
|
|
||||||
val oldRedisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token
|
|
||||||
redisUtil.delObject(oldRedisKey)
|
|
||||||
val jwt = JwtUtil.createJwt(WebUtil.getLoginUserId().toString())
|
|
||||||
|
|
||||||
jwt ?: let {
|
|
||||||
throw RuntimeException("Login failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
val redisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + jwt
|
|
||||||
redisUtil.setObject(
|
|
||||||
redisKey, loginUser, SecurityProperties.redisTtl, SecurityProperties.redisTtlUnit
|
|
||||||
)
|
|
||||||
|
|
||||||
return TokenVo(jwt)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
t_user.username as user_username,
|
t_user.username as user_username,
|
||||||
t_user.password as user_password,
|
t_user.password as user_password,
|
||||||
t_user.verify as user_verify,
|
t_user.verify as user_verify,
|
||||||
|
t_user.forget as user_forget,
|
||||||
t_user.locking as user_locking,
|
t_user.locking as user_locking,
|
||||||
t_user.expiration as user_expiration,
|
t_user.expiration as user_expiration,
|
||||||
t_user.credentials_expiration as user_credentials_expiration,
|
t_user.credentials_expiration as user_credentials_expiration,
|
||||||
@@ -128,6 +129,7 @@
|
|||||||
select t_user.id as user_id,
|
select t_user.id as user_id,
|
||||||
t_user.username as user_username,
|
t_user.username as user_username,
|
||||||
t_user.verify as user_verify,
|
t_user.verify as user_verify,
|
||||||
|
t_user.forget as user_forget,
|
||||||
t_user.locking as user_locking,
|
t_user.locking as user_locking,
|
||||||
t_user.expiration as user_expiration,
|
t_user.expiration as user_expiration,
|
||||||
t_user.credentials_expiration as user_credentials_expiration,
|
t_user.credentials_expiration as user_credentials_expiration,
|
||||||
@@ -179,6 +181,7 @@
|
|||||||
select t_user.id as user_id,
|
select t_user.id as user_id,
|
||||||
t_user.username as user_username,
|
t_user.username as user_username,
|
||||||
t_user.verify as user_verify,
|
t_user.verify as user_verify,
|
||||||
|
t_user.forget as user_forget,
|
||||||
t_user.locking as user_locking,
|
t_user.locking as user_locking,
|
||||||
t_user.expiration as user_expiration,
|
t_user.expiration as user_expiration,
|
||||||
t_user.credentials_expiration as user_credentials_expiration,
|
t_user.credentials_expiration as user_credentials_expiration,
|
||||||
@@ -227,6 +230,7 @@
|
|||||||
t_user.username as user_username,
|
t_user.username as user_username,
|
||||||
t_user.verify as user_verify,
|
t_user.verify as user_verify,
|
||||||
t_user.locking as user_locking,
|
t_user.locking as user_locking,
|
||||||
|
t_user.forget as user_forget,
|
||||||
t_user.expiration as user_expiration,
|
t_user.expiration as user_expiration,
|
||||||
t_user.credentials_expiration as user_credentials_expiration,
|
t_user.credentials_expiration as user_credentials_expiration,
|
||||||
t_user.enable as user_enable,
|
t_user.enable as user_enable,
|
||||||
@@ -284,6 +288,7 @@
|
|||||||
<id property="id" column="user_id"/>
|
<id property="id" column="user_id"/>
|
||||||
<result property="username" column="user_username"/>
|
<result property="username" column="user_username"/>
|
||||||
<result property="verify" column="user_verify"/>
|
<result property="verify" column="user_verify"/>
|
||||||
|
<result property="forget" column="user_forget"/>
|
||||||
<result property="locking" column="user_locking"/>
|
<result property="locking" column="user_locking"/>
|
||||||
<result property="expiration" column="user_expiration"/>
|
<result property="expiration" column="user_expiration"/>
|
||||||
<result property="credentialsExpiration" column="user_credentials_expiration"/>
|
<result property="credentialsExpiration" column="user_credentials_expiration"/>
|
||||||
@@ -299,7 +304,8 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<resultMap id="userWithInfoMap" type="user" extends="userBaseMap">
|
<resultMap id="userWithInfoMap" type="user" extends="userBaseMap">
|
||||||
<association property="userInfo" resultMap="top.fatweb.oxygen.api.mapper.permission.UserInfoMapper.userInfoMap"/>
|
<association property="userInfo"
|
||||||
|
resultMap="top.fatweb.oxygen.api.mapper.permission.UserInfoMapper.userInfoMap"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<resultMap id="userWithPowerInfoMap" type="user" extends="userWithInfoMap">
|
<resultMap id="userWithPowerInfoMap" type="user" extends="userWithInfoMap">
|
||||||
@@ -307,7 +313,8 @@
|
|||||||
<collection property="modules" resultMap="top.fatweb.oxygen.api.mapper.permission.ModuleMapper.moduleMap"/>
|
<collection property="modules" resultMap="top.fatweb.oxygen.api.mapper.permission.ModuleMapper.moduleMap"/>
|
||||||
<collection property="menus" resultMap="top.fatweb.oxygen.api.mapper.permission.MenuMapper.menuMap"/>
|
<collection property="menus" resultMap="top.fatweb.oxygen.api.mapper.permission.MenuMapper.menuMap"/>
|
||||||
<collection property="funcs" resultMap="top.fatweb.oxygen.api.mapper.permission.FuncMapper.funcMap"/>
|
<collection property="funcs" resultMap="top.fatweb.oxygen.api.mapper.permission.FuncMapper.funcMap"/>
|
||||||
<collection property="operations" resultMap="top.fatweb.oxygen.api.mapper.permission.OperationMapper.operationMap"/>
|
<collection property="operations"
|
||||||
|
resultMap="top.fatweb.oxygen.api.mapper.permission.OperationMapper.operationMap"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<resultMap id="userWithRoleInfoMap" type="user" extends="userWithInfoMap">
|
<resultMap id="userWithRoleInfoMap" type="user" extends="userWithInfoMap">
|
||||||
|
|||||||
Reference in New Issue
Block a user