Add login
This commit is contained in:
@@ -18,14 +18,12 @@ fun main(args: Array<String>) {
|
||||
runApplication<FatWebApiApplication>(*args)
|
||||
} else {
|
||||
logger.warn("File ‘application.yml’ cannot be found in the running path. The configuration file template 'application.example.yml' has been created. Please change the configuration file content and rename it to 'application.yml', and then restart the server.")
|
||||
FatWebApiApplication::class.java.getResource("/application-config-template.yml")?.readText()
|
||||
?.let {
|
||||
File("application-config.example.yml").writeText(
|
||||
it.replace(
|
||||
"\$uuid\$",
|
||||
UUID.randomUUID().toString()
|
||||
)
|
||||
FatWebApiApplication::class.java.getResource("/application-config-template.yml")?.readText()?.let {
|
||||
File("application-config.example.yml").writeText(
|
||||
it.replace(
|
||||
"\$uuid\$", UUID.randomUUID().toString().replace("-", "")
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@ package top.fatweb.api.annotation
|
||||
|
||||
import org.springframework.core.annotation.AliasFor
|
||||
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class ApiVersion(
|
||||
@get:AliasFor("version")
|
||||
val value: Int = 1,
|
||||
@get:AliasFor("version") val value: Int = 1,
|
||||
|
||||
@get:AliasFor("value")
|
||||
val version: Int = 1
|
||||
@get:AliasFor("value") val version: Int = 1
|
||||
)
|
||||
|
||||
@@ -2,20 +2,30 @@ package top.fatweb.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import io.swagger.v3.oas.annotations.tags.Tag
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import top.fatweb.api.annotation.ApiVersion
|
||||
import top.fatweb.api.entity.common.ResponseCode
|
||||
import top.fatweb.api.entity.common.ResponseResult
|
||||
import top.fatweb.api.entity.permission.User
|
||||
import top.fatweb.api.entity.converter.UserConverter
|
||||
import top.fatweb.api.entity.param.LoginParam
|
||||
import top.fatweb.api.service.permission.IAuthenticationService
|
||||
|
||||
@Tag(name = "身份认证", description = "身份认证相关接口")
|
||||
@RestController
|
||||
@Suppress("MVCPathVariableInspection")
|
||||
@RequestMapping("/api/{apiVersion}")
|
||||
@ApiVersion(2)
|
||||
class AuthenticationController(val loginService: IAuthenticationService) {
|
||||
@RestController
|
||||
class AuthenticationController(val loginService: IAuthenticationService, val userConverter: UserConverter) {
|
||||
@Operation(summary = "登录")
|
||||
@PostMapping("/login")
|
||||
fun login(@PathVariable apiVersion: String, @RequestBody user: User) =
|
||||
ResponseResult.success(ResponseCode.SYSTEM_LOGIN_SUCCESS, "Login success", loginService.login(user))
|
||||
fun login(@Valid @RequestBody loginParam: LoginParam) =
|
||||
ResponseResult.success(
|
||||
ResponseCode.SYSTEM_LOGIN_SUCCESS,
|
||||
"Login success",
|
||||
loginService.login(userConverter.loginParamToUser(loginParam))
|
||||
)
|
||||
}
|
||||
@@ -7,14 +7,16 @@ enum class ResponseCode(val code: Int) {
|
||||
SYSTEM_LOGOUT_SUCCESS(BusinessCode.SYSTEM, 22),
|
||||
SYSTEM_TOKEN_RENEW_SUCCESS(BusinessCode.SYSTEM, 23),
|
||||
SYSTEM_UNAUTHORIZED(BusinessCode.SYSTEM, 30),
|
||||
SYSTEM_ACCESS_DENIED(BusinessCode.SYSTEM, 31),
|
||||
SYSTEM_USER_DISABLE(BusinessCode.SYSTEM, 32),
|
||||
SYSTEM_LOGIN_USERNAME_PASSWORD_ERROR(BusinessCode.SYSTEM, 33),
|
||||
SYSTEM_OLD_PASSWORD_NOT_MATCH(BusinessCode.SYSTEM, 34),
|
||||
SYSTEM_LOGOUT_FAILED(BusinessCode.SYSTEM, 35),
|
||||
SYSTEM_TOKEN_ILLEGAL(BusinessCode.SYSTEM, 36),
|
||||
SYSTEM_TOKEN_HAS_EXPIRED(BusinessCode.SYSTEM, 37),
|
||||
SYSTEM_USERNAME_NOT_FOUND(BusinessCode.SYSTEM, 31),
|
||||
SYSTEM_ACCESS_DENIED(BusinessCode.SYSTEM, 32),
|
||||
SYSTEM_USER_DISABLE(BusinessCode.SYSTEM, 33),
|
||||
SYSTEM_LOGIN_USERNAME_PASSWORD_ERROR(BusinessCode.SYSTEM, 34),
|
||||
SYSTEM_OLD_PASSWORD_NOT_MATCH(BusinessCode.SYSTEM, 35),
|
||||
SYSTEM_LOGOUT_FAILED(BusinessCode.SYSTEM, 36),
|
||||
SYSTEM_TOKEN_ILLEGAL(BusinessCode.SYSTEM, 37),
|
||||
SYSTEM_TOKEN_HAS_EXPIRED(BusinessCode.SYSTEM, 38),
|
||||
SYSTEM_REQUEST_ILLEGAL(BusinessCode.SYSTEM, 40),
|
||||
SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 41),
|
||||
SYSTEM_ERROR(BusinessCode.SYSTEM, 50),
|
||||
SYSTEM_TIMEOUT(BusinessCode.SYSTEM, 51);
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package top.fatweb.api.entity.converter
|
||||
|
||||
import org.mapstruct.Mapper
|
||||
import org.mapstruct.Mapping
|
||||
import org.mapstruct.Mappings
|
||||
import top.fatweb.api.entity.param.LoginParam
|
||||
import top.fatweb.api.entity.permission.User
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
interface UserConverter {
|
||||
@Mappings(Mapping(source = "username", target = "username"), Mapping(source = "password", target = "password"))
|
||||
fun loginParamToUser(loginParam: LoginParam): User
|
||||
|
||||
}
|
||||
16
src/main/kotlin/top/fatweb/api/entity/param/LoginParam.kt
Normal file
16
src/main/kotlin/top/fatweb/api/entity/param/LoginParam.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.api.entity.param
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
import java.io.Serializable
|
||||
|
||||
class LoginParam : Serializable {
|
||||
|
||||
@Schema(description = "用户名", example = "test", required = true)
|
||||
@NotBlank(message = "Username can not be blank")
|
||||
val username: String? = null
|
||||
|
||||
@Schema(description = "密码", example = "test123456", required = true)
|
||||
@NotBlank(message = "Password can not be blank")
|
||||
val password: String? = null
|
||||
}
|
||||
@@ -12,7 +12,12 @@ import java.io.Serializable
|
||||
* @since 2023-10-04
|
||||
*/
|
||||
@TableName("t_user")
|
||||
class User : Serializable {
|
||||
class User() : Serializable {
|
||||
constructor(username: String, password: String, enable: Boolean = true) : this() {
|
||||
this.username = username
|
||||
this.password = password
|
||||
this.enable = if (enable) 1 else 0
|
||||
}
|
||||
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
@@ -44,13 +49,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, enable=$enable, deleted=$deleted, version=$version}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package top.fatweb.api.handler
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException
|
||||
import org.springframework.security.authentication.BadCredentialsException
|
||||
import org.springframework.security.authentication.InsufficientAuthenticationException
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
import top.fatweb.api.entity.common.ResponseCode
|
||||
@@ -26,6 +29,22 @@ class ExceptionHandler {
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage.split(":")[0], null)
|
||||
}
|
||||
|
||||
is MethodArgumentNotValidException -> {
|
||||
log.debug(e.localizedMessage, e)
|
||||
val errorMessage = e.allErrors.map { error -> error.defaultMessage }.joinToString(". ")
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null)
|
||||
}
|
||||
|
||||
is InternalAuthenticationServiceException -> {
|
||||
log.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_USERNAME_NOT_FOUND, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is BadCredentialsException -> {
|
||||
log.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_LOGIN_USERNAME_PASSWORD_ERROR, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
else -> {
|
||||
log.error(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_ERROR, data = null)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package top.fatweb.api.service.permission.impl
|
||||
|
||||
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.stereotype.Service
|
||||
import top.fatweb.api.entity.permission.LoginUser
|
||||
import top.fatweb.api.entity.permission.User
|
||||
import top.fatweb.api.service.IUserService
|
||||
|
||||
@Service
|
||||
class UserDetailsServiceImpl(val userService: IUserService) : UserDetailsService {
|
||||
override fun loadUserByUsername(username: String?): UserDetails {
|
||||
val user = userService.getOne(KtQueryWrapper(User()).eq(User::username, username))
|
||||
user ?: let { throw Exception("Username not found") }
|
||||
|
||||
return LoginUser(user)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ app:
|
||||
# token-prefix: "Bearer " # Token prefix
|
||||
# jwt-ttl: 2 # The life of token
|
||||
# jwt-ttl-unit: hours # Unit of life of token
|
||||
jwt-key: $uuid$ # Key to generate token
|
||||
jwt-key: $uuid$ # Key to generate token (Only numbers and letters allow)
|
||||
# jwt-issuer: FatWeb # Token issuer
|
||||
|
||||
server:
|
||||
|
||||
Reference in New Issue
Block a user