Add login IP record

This commit is contained in:
2023-10-16 17:35:34 +08:00
parent 1fcd468581
commit 8e3ceb16c1
7 changed files with 110 additions and 22 deletions

View File

@@ -4,7 +4,10 @@ import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.servlet.http.HttpServletRequest
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.ApiVersion
import top.fatweb.api.converter.UserConverter
import top.fatweb.api.entity.common.ResponseCode
@@ -19,11 +22,11 @@ import top.fatweb.api.util.WebUtil
class AuthenticationController(val authenticationService: IAuthenticationService, val userConverter: UserConverter) {
@Operation(summary = "登录")
@PostMapping("/login")
fun login(@Valid @RequestBody loginParam: LoginParam) =
fun login(request: HttpServletRequest, @Valid @RequestBody loginParam: LoginParam) =
ResponseResult.success(
ResponseCode.SYSTEM_LOGIN_SUCCESS,
"Login success",
authenticationService.login(userConverter.loginParamToUser(loginParam))
authenticationService.login(request, userConverter.loginParamToUser(loginParam))
)
@Operation(summary = "登出")

View File

@@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonTypeInfo
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import java.time.LocalDateTime
import java.time.ZoneOffset
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
class LoginUser() : UserDetails {
@@ -25,20 +27,22 @@ class LoginUser() : UserDetails {
}
@JsonIgnore
override fun getPassword(): String? = user.password
override fun getPassword() = user.password
@JsonIgnore
override fun getUsername(): String? = user.username
override fun getUsername() = user.username
@JsonIgnore
override fun isAccountNonExpired(): Boolean = true
override fun isAccountNonExpired() =
user.expiration == null || user.expiration!!.isAfter(LocalDateTime.now(ZoneOffset.UTC))
@JsonIgnore
override fun isAccountNonLocked(): Boolean = true
override fun isAccountNonLocked() = user.locking == 0
@JsonIgnore
override fun isCredentialsNonExpired(): Boolean = true
override fun isCredentialsNonExpired() =
user.credentialsExpiration == null || user.credentialsExpiration!!.isAfter(LocalDateTime.now(ZoneOffset.UTC))
@JsonIgnore
override fun isEnabled(): Boolean = user.enable == 1
override fun isEnabled() = user.enable == 1
}

View File

@@ -2,10 +2,11 @@ package top.fatweb.api.entity.permission
import com.baomidou.mybatisplus.annotation.*
import java.io.Serializable
import java.time.LocalDateTime
/**
* <p>
* 用户
* 用户
* </p>
*
* @author FatttSnake
@@ -13,7 +14,8 @@ import java.io.Serializable
*/
@TableName("t_user")
class User() : Serializable {
constructor(username: String, password: String, enable: Boolean = true) : this() {
constructor(id: Long?, username: String, password: String, enable: Boolean = true) : this() {
this.id = id
this.username = username
this.password = password
this.enable = if (enable) 1 else 0
@@ -34,12 +36,54 @@ class User() : Serializable {
@TableField("password")
var password: String? = null
/**
* 锁定
*/
@TableField("locking")
var locking: Int? = null
/**
* 过期时间
*/
@TableField("expiration")
var expiration: LocalDateTime? = null
/**
* 认证过期时间
*/
@TableField("credentials_expiration")
var credentialsExpiration: LocalDateTime? = null
/**
* 启用
*/
@TableField("enable")
var enable: Int? = null
/**
* 上次登录时间
*/
@TableField("last_login_time")
var lastLoginTime: LocalDateTime? = null
/**
* 上次登录 IP
*/
@TableField("last_login_ip")
var lastLoginIp: String? = null
/**
* 创建时间
*/
@TableField("create_time")
var createTime: LocalDateTime? = null
/**
* 修改时间
*/
@TableField("update_time")
var updateTime: LocalDateTime? = null
@TableField("deleted")
@TableLogic
var deleted: Long? = null
@@ -49,6 +93,6 @@ class User() : Serializable {
var version: Int? = null
override fun toString(): String {
return "User{id=$id, username=$username, password=$password, enable=$enable, deleted=$deleted, version=$version}"
return "User(id=$id, username=$username, password=$password, locking=$locking, expiration=$expiration, credentialsExpiration=$credentialsExpiration, enable=$enable, lastLoginTime=$lastLoginTime, lastLoginIp=$lastLoginIp, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version)"
}
}

View File

@@ -1,11 +1,12 @@
package top.fatweb.api.service.permission
import jakarta.servlet.http.HttpServletRequest
import top.fatweb.api.entity.permission.User
import top.fatweb.api.vo.LoginVo
import top.fatweb.api.vo.TokenVo
interface IAuthenticationService {
fun login(user: User): LoginVo
fun login(request: HttpServletRequest, user: User): LoginVo
fun logout(token: String): Boolean

View File

@@ -1,30 +1,46 @@
package top.fatweb.api.service.permission.impl
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper
import jakarta.servlet.http.HttpServletRequest
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.stereotype.Service
import top.fatweb.api.constant.SecurityConstants
import top.fatweb.api.entity.permission.LoginUser
import top.fatweb.api.entity.permission.User
import top.fatweb.api.service.IUserService
import top.fatweb.api.service.permission.IAuthenticationService
import top.fatweb.api.util.JwtUtil
import top.fatweb.api.util.RedisUtil
import top.fatweb.api.util.WebUtil
import top.fatweb.api.vo.LoginVo
import top.fatweb.api.vo.TokenVo
import java.time.LocalDateTime
import java.time.ZoneOffset
@Service
class AuthenticationServiceImpl(
private val authenticationManager: AuthenticationManager,
private val redisUtil: RedisUtil
private val redisUtil: RedisUtil,
private val userService: IUserService
) : IAuthenticationService {
override fun login(user: User): LoginVo {
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
override fun login(request: HttpServletRequest, user: User): LoginVo {
val usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken(user.username, user.password)
val authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken)
authentication ?: let {
throw RuntimeException("Login failed")
}
logger.info("用户登录 [用户名: '{}', IP: '{}']", user.username, request.remoteAddr)
userService.update(User().apply {
lastLoginIp = request.remoteAddr
lastLoginTime = LocalDateTime.now(ZoneOffset.UTC)
}, KtUpdateWrapper(User()).eq(User::username, user.username))
val loginUser = authentication.principal as LoginUser
loginUser.user.password = ""
val userId = loginUser.user.id.toString()

View File

@@ -3,12 +3,15 @@ package top.fatweb.api
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.test.context.junit.jupiter.SpringExtension
import top.fatweb.api.constant.SecurityConstants
import top.fatweb.api.util.JwtUtil
@ExtendWith(SpringExtension::class)
class FatWebApiApplicationTests {
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
@Test
fun removePrefixTest() {
@@ -20,4 +23,12 @@ class FatWebApiApplicationTests {
val jwt = JwtUtil.createJwt("User")
assertEquals("User", jwt?.let { JwtUtil.parseJwt(it).subject })
}
/*
@Test
fun generatePassword() {
val passwordEncoder = BCryptPasswordEncoder()
logger.info(passwordEncoder.encode("admin@dev"))
}
*/
}