feat(新增): 用户认证
This commit is contained in:
parent
175e238852
commit
91bf18844a
|
@ -30,7 +30,7 @@ open class BaseContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getLoginVo(): LoginVo? {
|
fun getLoginVo(): LoginVo {
|
||||||
return loginVo.get()
|
return loginVo.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,15 @@ import lombok.NoArgsConstructor
|
||||||
@Schema(name = "EmailTemplateDto", title = "邮箱模板请求内容", description = "邮箱模板请求内容")
|
@Schema(name = "EmailTemplateDto", title = "邮箱模板请求内容", description = "邮箱模板请求内容")
|
||||||
class EmailTemplateDto {
|
class EmailTemplateDto {
|
||||||
@Schema(name = "templateName", title = "模板名称")
|
@Schema(name = "templateName", title = "模板名称")
|
||||||
var templateName: @NotBlank(message = "模板名称不能为空") String? = null
|
var templateName: String? = null
|
||||||
|
|
||||||
@Schema(name = "subject", title = "主题")
|
@Schema(name = "subject", title = "主题")
|
||||||
var subject: @NotBlank(message = "主题不能为空") String? = null
|
@NotBlank(message = "主题不能为空")
|
||||||
|
var subject: String? = null
|
||||||
|
|
||||||
@Schema(name = "body", title = "邮件内容")
|
@Schema(name = "body", title = "邮件内容")
|
||||||
var body: @NotBlank(message = "邮件内容不能为空") String? = null
|
@NotBlank(message = "邮件内容不能为空")
|
||||||
|
var body: String? = null
|
||||||
|
|
||||||
@Schema(name = "type", title = "邮件类型")
|
@Schema(name = "type", title = "邮件类型")
|
||||||
var type: String? = null
|
var type: String? = null
|
||||||
|
|
|
@ -18,19 +18,23 @@ import lombok.NoArgsConstructor
|
||||||
@Schema(name = "EmailUsersDto", title = "邮箱用户发送基础内容", description = "邮箱用户发送基础内容")
|
@Schema(name = "EmailUsersDto", title = "邮箱用户发送基础内容", description = "邮箱用户发送基础内容")
|
||||||
class EmailUsersDto {
|
class EmailUsersDto {
|
||||||
@Schema(name = "id", title = "主键")
|
@Schema(name = "id", title = "主键")
|
||||||
var id: @NotBlank(message = "id不能为空") Long? = null
|
@NotBlank(message = "id不能为空")
|
||||||
|
var id: Long? = null
|
||||||
|
|
||||||
@Schema(name = "email", title = "邮箱")
|
@Schema(name = "email", title = "邮箱")
|
||||||
var email: @NotBlank(message = "邮箱不能为空") String? = null
|
@NotBlank(message = "邮箱不能为空")
|
||||||
|
var email: String? = null
|
||||||
|
|
||||||
@Schema(name = "password", title = "密码")
|
@Schema(name = "password", title = "密码")
|
||||||
var password: @NotBlank(message = "密码不能为空") String? = null
|
@NotBlank(message = "密码不能为空")
|
||||||
|
var password: String? = null
|
||||||
|
|
||||||
@Schema(name = "host", title = "SMTP服务器")
|
@Schema(name = "host", title = "SMTP服务器")
|
||||||
var host: String? = null
|
var host: String? = null
|
||||||
|
|
||||||
@Schema(name = "port", title = "端口号")
|
@Schema(name = "port", title = "端口号")
|
||||||
var port: @NotNull(message = "端口号不能为空") Int? = null
|
@NotNull(message = "端口号不能为空")
|
||||||
|
var port: Int? = null
|
||||||
|
|
||||||
@Schema(name = "smtpAgreement", title = "邮箱协议")
|
@Schema(name = "smtpAgreement", title = "邮箱协议")
|
||||||
var smtpAgreement: Int? = null
|
var smtpAgreement: Int? = null
|
||||||
|
|
|
@ -13,6 +13,7 @@ enum class ResultCodeEnum(val code: Int, val message: String) {
|
||||||
EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"),
|
EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"),
|
||||||
|
|
||||||
// 验证错误 201
|
// 验证错误 201
|
||||||
|
LOGIN_AUTH(208, "请先登陆"),
|
||||||
USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"),
|
USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"),
|
||||||
EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"),
|
EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"),
|
||||||
EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"),
|
EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"),
|
||||||
|
@ -28,7 +29,6 @@ enum class ResultCodeEnum(val code: Int, val message: String) {
|
||||||
EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"),
|
EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"),
|
||||||
|
|
||||||
// 身份过期 208
|
// 身份过期 208
|
||||||
LOGIN_AUTH(208, "请先登陆"),
|
|
||||||
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
|
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
|
||||||
|
|
||||||
// 封禁 209
|
// 封禁 209
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.bunny.services.security.config
|
package cn.bunny.services.security.config
|
||||||
|
|
||||||
import cn.bunny.services.security.custom.CustomPasswordEncoder
|
import cn.bunny.services.security.custom.CustomPasswordEncoder
|
||||||
|
import cn.bunny.services.security.filter.NoTokenAuthenticationFilter
|
||||||
import cn.bunny.services.security.filter.TokenAuthenticationFilter
|
import cn.bunny.services.security.filter.TokenAuthenticationFilter
|
||||||
import cn.bunny.services.security.filter.TokenLoginFilterService
|
import cn.bunny.services.security.filter.TokenLoginFilterService
|
||||||
import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler
|
import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler
|
||||||
|
@ -75,6 +76,7 @@ class WebSecurityConfig {
|
||||||
UsernamePasswordAuthenticationFilter::class.java
|
UsernamePasswordAuthenticationFilter::class.java
|
||||||
)
|
)
|
||||||
// 其它权限鉴权过滤器
|
// 其它权限鉴权过滤器
|
||||||
|
.addFilterAt(NoTokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter::class.java)
|
||||||
.addFilterAt(TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter::class.java)
|
.addFilterAt(TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter::class.java)
|
||||||
// 自定义密码加密器和用户登录
|
// 自定义密码加密器和用户登录
|
||||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService)
|
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package cn.bunny.services.security.filter
|
||||||
|
|
||||||
|
import cn.bunny.common.service.context.BaseContext
|
||||||
|
import cn.bunny.common.service.utils.JwtHelper
|
||||||
|
import cn.bunny.common.service.utils.ResponseUtil.Companion.out
|
||||||
|
import cn.bunny.dao.pojo.constant.RedisUserConstant
|
||||||
|
import cn.bunny.dao.pojo.result.Result
|
||||||
|
import cn.bunny.dao.pojo.result.ResultCodeEnum
|
||||||
|
import cn.bunny.dao.vo.user.LoginVo
|
||||||
|
import jakarta.servlet.FilterChain
|
||||||
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
|
import jakarta.servlet.http.HttpServletResponse
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter
|
||||||
|
|
||||||
|
class NoTokenAuthenticationFilter(private val redisTemplate: RedisTemplate<Any, Any?>) : OncePerRequestFilter() {
|
||||||
|
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
|
||||||
|
// 判断是否有token
|
||||||
|
val token = request.getHeader("token") ?: run {
|
||||||
|
out(response, Result.error(ResultCodeEnum.LOGIN_AUTH))
|
||||||
|
return@doFilterInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断token是否过期
|
||||||
|
val expired = JwtHelper.isExpired(token)
|
||||||
|
if (expired) {
|
||||||
|
out(response, Result.error(ResultCodeEnum.AUTHENTICATION_EXPIRED))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// token存在查找Redis
|
||||||
|
val username = JwtHelper.getUsername(token)!!
|
||||||
|
val userId = JwtHelper.getUserId(token)!!
|
||||||
|
val loginVo: LoginVo? = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username)) as LoginVo?
|
||||||
|
|
||||||
|
// 判断用户是否禁用
|
||||||
|
if (loginVo?.status == 1.toByte()) {
|
||||||
|
out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置用户信息
|
||||||
|
BaseContext.setUsername(username)
|
||||||
|
BaseContext.setUserId(userId)
|
||||||
|
BaseContext.setLoginVo(loginVo!!)
|
||||||
|
|
||||||
|
// 执行下一个过滤器
|
||||||
|
doFilter(request, response, filterChain)
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,14 +16,6 @@ import java.util.function.Consumer
|
||||||
class TokenAuthenticationFilter(private val redisTemplate: RedisTemplate<Any, Any?>) : OncePerRequestFilter() {
|
class TokenAuthenticationFilter(private val redisTemplate: RedisTemplate<Any, Any?>) : OncePerRequestFilter() {
|
||||||
@Throws(ServletException::class, IOException::class, BunnyException::class)
|
@Throws(ServletException::class, IOException::class, BunnyException::class)
|
||||||
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
|
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
|
||||||
val token = request.getHeader("token")
|
|
||||||
|
|
||||||
// 判断是否有token,如果后面还有过滤器就这样写
|
|
||||||
// if (token == null) {
|
|
||||||
// doFilter(request, response, chain)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// 自定义实现内容
|
// 自定义实现内容
|
||||||
val authentication = getAuthentication(request)
|
val authentication = getAuthentication(request)
|
||||||
|
@ -31,6 +23,8 @@ class TokenAuthenticationFilter(private val redisTemplate: RedisTemplate<Any, An
|
||||||
|
|
||||||
chain.doFilter(request, response)
|
chain.doFilter(request, response)
|
||||||
}
|
}
|
||||||
|
// 判断是否有token,如果后面还有过滤器就这样写
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 用户请求判断
|
* * 用户请求判断
|
||||||
|
|
|
@ -36,8 +36,7 @@ class CustomUserDetailsServiceImpl : CustomUserDetailsService {
|
||||||
val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username).or().eq(AdminUser::username, username)
|
val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username).or().eq(AdminUser::username, username)
|
||||||
|
|
||||||
// 根据邮箱查询用户名
|
// 根据邮箱查询用户名
|
||||||
val user = userMapper.selectOne(queryWrapper)
|
val user = userMapper.selectOne(queryWrapper) ?: throw UsernameNotFoundException("用户不存在")
|
||||||
user ?: throw UsernameNotFoundException("用户不存在 ")
|
|
||||||
|
|
||||||
// 根据用户id查询当前用户所有角色
|
// 根据用户id查询当前用户所有角色
|
||||||
val roleList: List<Role> = roleMapper.selectListByUserId(user.id!!)
|
val roleList: List<Role> = roleMapper.selectListByUserId(user.id!!)
|
||||||
|
|
|
@ -95,7 +95,7 @@ internal class UserServiceImpl : ServiceImpl<UserMapper?, AdminUser?>(), UserSer
|
||||||
* * 退出登录
|
* * 退出登录
|
||||||
*/
|
*/
|
||||||
override fun logOut() {
|
override fun logOut() {
|
||||||
val loginVo = BaseContext.getLoginVo() ?: throw BunnyException(ResultCodeEnum.FAIL_REQUEST_NOT_AUTH)
|
val loginVo = BaseContext.getLoginVo()
|
||||||
redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(loginVo.username!!))
|
redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(loginVo.username!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue