配置操作

This commit is contained in:
筱锋xiao_lfeng 2023-11-29 22:14:40 +08:00
parent 698f63507f
commit 86006196c8
5 changed files with 291 additions and 0 deletions

View File

@ -0,0 +1,54 @@
package com.xlf.dromstarkotlin.controllers
import com.frontleaves.general.utils.BaseResponse
import com.frontleaves.general.utils.ResultUtil
import com.xlf.dromstarkotlin.services.TokenService
import jakarta.servlet.http.Cookie
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/api/token")
@CrossOrigin(origins = ["*"])
class TokenController(
private val tokenService: TokenService
) {
/**
* 创建 Token 组件
*/
@PostMapping("/create")
fun createToken(
@CookieValue("session") token: String?, httpServletResponse: HttpServletResponse,
@RequestParam("return") returnLink: String?,
httpServletRequest: HttpServletRequest
): ResponseEntity<BaseResponse> {
// 检查 token 是否存在
return if (token == null) {
val newToken = tokenService.tokenCreate(httpServletRequest)
httpServletResponse.addCookie(
Cookie("session", newToken)
.also { it.path = "/" }
.also { it.maxAge = 43200 }
)
ResultUtil.redirect("SuccessCreate", "Token创建成功", newToken, returnLink, httpServletRequest)
} else {
if (tokenService.tokenVerify(token, httpServletResponse)) {
ResultUtil.redirect("StillValid", "Token依旧有效", null, returnLink, httpServletRequest)
} else {
httpServletResponse.addCookie(
Cookie("session", null)
.also { it.path = "/" }
.also { it.maxAge = 0 }
)
this.createToken(null, httpServletResponse, returnLink, httpServletRequest)
}
}
}
}

View File

@ -0,0 +1,55 @@
package com.xlf.dromstarkotlin.controllers
import com.frontleaves.general.utils.BaseResponse
import com.frontleaves.general.utils.ErrorCode
import com.frontleaves.general.utils.ResultUtil
import com.xlf.dromstarkotlin.entity.voData.SignInVO
import com.xlf.dromstarkotlin.exception.BusinessException
import com.xlf.dromstarkotlin.services.TokenService
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/**
* 用户控制器
*
* 对用户进行管理和操作
*
* @author 筱锋xiao_lfeng
* @since v1.0.0
*/
@RestController
@RequestMapping("/api/user")
class UserController(
private val tokenService: TokenService
) {
/**
* 用户登录组件
*/
@PostMapping("/sign/in")
fun signIn(
signInVO: SignInVO?, @CookieValue("sessionId") token: String?, httpServletResponse: HttpServletResponse,
httpServletRequest: HttpServletRequest
): ResponseEntity<BaseResponse>? {
if (signInVO == null) {
return BusinessException().backInfo(ErrorCode.MISSING_REQUEST_BODY, httpServletRequest)
} else {
// 对 Token 进行校验
if (token != null) {
// 对 token 进行校验
if (!tokenService.tokenVerify(token, httpServletResponse)) {
// 校验失败
return BusinessException().backInfo(ErrorCode.TOKEN_VERIFY_FAILED, httpServletRequest)
}
} else {
// 跳转至创建 Token 页面
return ResultUtil.redirect("/api/token/create", httpServletRequest)
}
}
return null
}
}

View File

@ -0,0 +1,45 @@
package com.xlf.dromstarkotlin.services
import com.frontleaves.general.utils.ErrorCode
import com.xlf.dromstarkotlin.cache.CacheData
import com.xlf.dromstarkotlin.cache.CacheToken
import com.xlf.dromstarkotlin.exception.BusinessException
import jakarta.servlet.http.HttpServletRequest
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Component
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import java.util.Date
@Aspect
@Component
class PreOperation {
/**
* 对用户访问量进行控制
*/
@Around("execution(* com.xlf.dromstarkotlin.controllers.TokenController.*(..))")
fun tokenCheckService(proceedingJoinPoint: ProceedingJoinPoint): ResponseEntity<out Any>? {
val requestAttributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes?
val httpServletRequest = requestAttributes?.request as HttpServletRequest
// 检查
if (CacheData.tokenVisits[httpServletRequest.remoteAddr] == null) {
CacheData.tokenVisits[httpServletRequest.remoteAddr] = CacheToken(1, Date().time)
} else {
if (CacheData.tokenVisits[httpServletRequest.remoteAddr]!!.timestamp + 60000 > Date().time) {
if (CacheData.tokenVisits[httpServletRequest.remoteAddr]!!.count > 20L) {
return BusinessException().backInfo(ErrorCode.QPS_LIMITATION_VISIT, httpServletRequest)
} else {
CacheData.tokenVisits[httpServletRequest.remoteAddr]!!.count += 1
}
} else {
// 删除内容
CacheData.tokenVisits.remove(httpServletRequest.remoteAddr)
}
}
return proceedingJoinPoint.proceed() as ResponseEntity<*>?
}
}

View File

@ -0,0 +1,43 @@
package com.xlf.dromstarkotlin.services
import com.xlf.dromstarkotlin.mapper.TokenMapper
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import java.text.SimpleDateFormat
import java.util.*
@Component
class ScheduleService(
val tokenMapper: TokenMapper
) {
@Scheduled(fixedDelay = 900000)
fun clearExpiredToken() {
// 循环所有 Token 信息
val getToken = tokenMapper.getAllToken()
var i = 0
if (getToken != null) {
for (tokenInfo in getToken) {
if (tokenInfo.userId != null) {
if (tokenInfo.updatedAt != null) {
if (tokenInfo.updatedAt!!.time + 43200000 < Date().time) {
tokenMapper.deleteToken(tokenInfo.token!!)
i++
}
} else {
if (tokenInfo.createdAt!!.time + 43200000 < Date().time) {
tokenMapper.deleteToken(tokenInfo.token!!)
i++
}
}
} else {
if (tokenInfo.createdAt!!.time + 300000 < Date().time) {
tokenMapper.deleteToken(tokenInfo.token!!)
i++
}
}
}
}
println("${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())} [Log] <----->Scheduled | Message:clear token $i")
}
}

View File

@ -0,0 +1,94 @@
package com.xlf.dromstarkotlin.services
import com.xlf.dromstarkotlin.entity.doData.TokenDO
import com.xlf.dromstarkotlin.mapper.TokenMapper
import com.xlf.dromstarkotlin.utils.Processing
import jakarta.servlet.http.Cookie
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.sql.Timestamp
import java.util.Date
/**
* Token 控制器
*
* 对本系统的进行授权操作
*
* @since v1.0.0
* @author 筱锋xiao_lfeng
*/
@Service
class TokenService(
private val tokenMapper: TokenMapper
) {
/**
* token 进行校验
*/
@Transactional
fun tokenVerify(token: String, httpServletResponse: HttpServletResponse): Boolean {
val tokenDO = tokenMapper.getToken(token)
// 判断 token 是否存在
if (tokenDO != null) {
// 已登录用户
if (tokenDO.userId != null) {
// 判断 token 是否过期
if (tokenDO.updatedAt != null) {
if (tokenDO.updatedAt!!.time + 43200000 > Date().time) {
return true
} else {
tokenMapper.deleteToken(token)
val cookie = Cookie("session", null).also { it.maxAge = 0 }.also { it.path = "/" }
httpServletResponse.addCookie(cookie)
}
} else {
if (tokenDO.createdAt!!.time + 43200000 > Date().time) {
return true
} else {
tokenMapper.deleteToken(token)
val cookie = Cookie("session", null).also { it.maxAge = 0 }.also { it.path = "/" }
httpServletResponse.addCookie(cookie)
}
}
} else {
// 未登录用户
if (tokenDO.createdAt!!.time + 300000 > Date().time) {
return true
} else {
tokenMapper.deleteToken(token)
val cookie = Cookie("session", null).also { it.maxAge = 0 }.also { it.path = "/" }
httpServletResponse.addCookie(cookie)
}
}
}
return false
}
/**
* 创建 token
*/
@Transactional
fun tokenCreate(httpServletRequest: HttpServletRequest): String {
var token: String
var tokenDO: TokenDO?
do {
// 创建 token
token = Processing.createToken()
// 检查 token 是否存在
tokenDO = tokenMapper.getToken(token)
} while (tokenDO != null)
// 不存在则创建
val newTokenDO = TokenDO(
null,
null,
token,
httpServletRequest.getHeader("User-Agent"),
httpServletRequest.localAddr,
Timestamp(Date().time),
null
)
tokenMapper.insertToken(newTokenDO)
return token
}
}