feat(新增): 用户登录完成

This commit is contained in:
Bunny 2024-09-26 22:19:51 +08:00
parent 8fae01c4a2
commit 3783a74b56
19 changed files with 142 additions and 266 deletions

View File

@ -20,14 +20,15 @@ class AdminGenerator {
private const val AUTHOR: String = "Bunny" private const val AUTHOR: String = "Bunny"
// 公共路径 // 公共路径
private const val OUTPUT_DIR: String = "D:\\MyFolder\\auth-admin\\auth-server\\services" // private const val OUTPUT_DIR: String = "D:\\MyFolder\\auth-admin\\auth-server\\services"
private const val OUTPUT_DIR: String = "D:\\Project\\web\\PC\\auth\\auth-server\\services"
// 实体类名称 // 实体类名称
private const val ENTITY: String = "Bunny" private const val ENTITY: String = "Bunny"
@JvmStatic @JvmStatic
fun main(args: Array<String>) { fun main(args: Array<String>) {
generation("sys_email_template") generation("sys_power", "sys_role", "sys_role_power", "sys_user_role", "sys_router_power", "sys_router_role")
} }
/** /**

View File

@ -28,7 +28,9 @@ class MyBatisPlusFieldConfig : MetaObjectHandler {
* 使用mp做修改操作时候这个方法执行 * 使用mp做修改操作时候这个方法执行
*/ */
override fun updateFill(metaObject: MetaObject) { override fun updateFill(metaObject: MetaObject) {
if (BaseContext.getUserId() != null) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::class.java, LocalDateTime.now()) this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::class.java, LocalDateTime.now())
this.strictUpdateFill(metaObject, "updateUser", Long::class.java, BaseContext.getUserId()) this.strictUpdateFill(metaObject, "updateUser", Long::class.java, BaseContext.getUserId())
} }
}
} }

View File

@ -10,7 +10,7 @@ open class BaseContext {
// 用户id相关 // 用户id相关
@JvmStatic @JvmStatic
fun getUserId(): Long { fun getUserId(): Long? {
return userId.get() return userId.get()
} }

View File

@ -12,10 +12,10 @@ object JwtHelper {
private const val TOKEN_EXPIRATION = (24 * 60 * 60 * 1000).toLong() private const val TOKEN_EXPIRATION = (24 * 60 * 60 * 1000).toLong()
// JWT 的 秘钥 // JWT 的 秘钥
private const val TOKEN_SIGN_KEY = "Bunny-Java-Template" private const val TOKEN_SIGN_KEY = "Bunny-Kotlin-Template"
// 默认主题 // 默认主题
private const val SUBJECT = "Bunny" private const val SUBJECT = "Bunny-Admin"
// 默认时间 // 默认时间
private val time = Date(System.currentTimeMillis() + TOKEN_EXPIRATION * 7) private val time = Date(System.currentTimeMillis() + TOKEN_EXPIRATION * 7)

View File

@ -4,26 +4,25 @@ import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.NotBlank
import lombok.AllArgsConstructor import lombok.AllArgsConstructor
import lombok.Builder import lombok.Builder
import lombok.Data
import lombok.NoArgsConstructor import lombok.NoArgsConstructor
import lombok.experimental.Accessors
@Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
@Accessors(chain = true)
@Schema(name = "LoginDto", title = "登录表单内容", description = "登录表单内容") @Schema(name = "LoginDto", title = "登录表单内容", description = "登录表单内容")
class LoginDto { data class LoginDto(
@Schema(name = "username", title = "用户名") @Schema(name = "username", title = "用户名")
var username: @NotBlank(message = "用户名不能为空") String? = null @NotBlank(message = "用户名不能为空")
var username: String? = null,
@Schema(name = "password", title = "密码") @Schema(name = "password", title = "密码")
var password: @NotBlank(message = "密码不能为空") String? = null @NotBlank(message = "密码不能为空")
var password: String? = null,
@Schema(name = "emailCode", title = "邮箱验证码") @Schema(name = "emailCode", title = "邮箱验证码")
var emailCode: @NotBlank(message = "邮箱验证码不能为空") String? = null @NotBlank(message = "邮箱验证码不能为空")
var emailCode: String? = null,
@Schema(name = "readMeDay", title = "记住我的天数") @Schema(name = "readMeDay", title = "记住我的天数")
var readMeDay: Long = 7 var readMeDay: Long = 1,
} )

View File

@ -3,8 +3,6 @@ package cn.bunny.dao.entity.system
import cn.bunny.dao.entity.BaseEntity import cn.bunny.dao.entity.BaseEntity
import com.baomidou.mybatisplus.annotation.TableName import com.baomidou.mybatisplus.annotation.TableName
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import lombok.Getter
import lombok.Setter
import lombok.experimental.Accessors import lombok.experimental.Accessors
/** /**
@ -16,42 +14,40 @@ import lombok.experimental.Accessors
* @author Bunny * @author Bunny
* @since 2024-09-26 * @since 2024-09-26
*/ */
@Getter
@Setter
@Accessors(chain = true) @Accessors(chain = true)
@TableName("sys_user") @TableName("sys_user")
@Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息") @Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息")
class AdminUser : BaseEntity() { data class AdminUser(
@Schema(name = "username", title = "用户名") @Schema(name = "username", title = "用户名")
var username: String? = null var username: String? = null,
@Schema(name = "nickName", title = "昵称") @Schema(name = "nickName", title = "昵称")
var nickName: String? = null var nickName: String? = null,
@Schema(name = "email", title = "邮箱") @Schema(name = "email", title = "邮箱")
var email: String? = null var email: String? = null,
@Schema(name = "phone", title = "手机号") @Schema(name = "phone", title = "手机号")
var phone: String? = null var phone: String? = null,
@Schema(name = "password", title = "密码") @Schema(name = "password", title = "密码")
var password: String? = null var password: String? = null,
@Schema(name = "avatar", title = "头像") @Schema(name = "avatar", title = "头像")
var avatar: String? = null var avatar: String? = null,
@Schema(name = "sex", title = "性别", description = "0:女 1:男") @Schema(name = "sex", title = "性别", description = "0:女 1:男")
var sex: Byte? = null var sex: Byte? = null,
@Schema(name = "summary", title = "个人描述") @Schema(name = "summary", title = "个人描述")
var summary: String? = null var summary: String? = null,
@Schema(name = "lastLoginIp", title = "最后登录IP") @Schema(name = "lastLoginIp", title = "最后登录IP")
var lastLoginIp: String? = null var lastLoginIp: String? = null,
@Schema(name = "lastLoginIpAddress", title = "最后登录ip归属地") @Schema(name = "lastLoginIpAddress", title = "最后登录ip归属地")
var lastLoginIpAddress: String? = null var lastLoginIpAddress: String? = null,
@Schema(name = "status", title = "状态", description = "1:禁用 0:正常") @Schema(name = "status", title = "状态", description = "1:禁用 0:正常")
var status: Byte? = null var status: Byte? = null,
} ) : BaseEntity()

View File

@ -3,8 +3,6 @@ package cn.bunny.dao.entity.system
import cn.bunny.dao.entity.BaseEntity import cn.bunny.dao.entity.BaseEntity
import com.baomidou.mybatisplus.annotation.TableName import com.baomidou.mybatisplus.annotation.TableName
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import lombok.Getter
import lombok.Setter
import lombok.experimental.Accessors import lombok.experimental.Accessors
/** /**
@ -16,24 +14,22 @@ import lombok.experimental.Accessors
* @author Bunny * @author Bunny
* @since 2024-09-26 * @since 2024-09-26
*/ */
@Getter
@Setter
@Accessors(chain = true) @Accessors(chain = true)
@TableName("sys_email_template") @TableName("sys_email_template")
@Schema(name = "EmailTemplate对象", title = "邮件模板表", description = "邮件模板表") @Schema(name = "EmailTemplate对象", title = "邮件模板表", description = "邮件模板表")
class EmailTemplate : BaseEntity() { data class EmailTemplate(
@Schema(name = "email", title = "模板名称") @Schema(name = "email", title = "模板名称")
var templateName: String? = null var templateName: String? = null,
@Schema(name = "subject", title = "主题") @Schema(name = "subject", title = "主题")
var subject: String? = null var subject: String? = null,
@Schema(name = "body", title = "邮件内容") @Schema(name = "body", title = "邮件内容")
var body: String? = null var body: String? = null,
@Schema(name = "type", title = "邮件类型") @Schema(name = "type", title = "邮件类型")
var type: String? = null var type: String? = null,
@Schema(name = "isDefault", title = "是否默认") @Schema(name = "isDefault", title = "是否默认")
var isDefault: Boolean? = null var isDefault: Boolean? = null,
} ) : BaseEntity()

View File

@ -3,7 +3,6 @@ package cn.bunny.dao.entity.system
import cn.bunny.dao.entity.BaseEntity import cn.bunny.dao.entity.BaseEntity
import com.baomidou.mybatisplus.annotation.TableName import com.baomidou.mybatisplus.annotation.TableName
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import lombok.Data
import lombok.experimental.Accessors import lombok.experimental.Accessors
/** /**
@ -15,30 +14,28 @@ import lombok.experimental.Accessors
* @author Bunny * @author Bunny
* @since 2024-09-26 * @since 2024-09-26
*/ */
@Data
@Accessors(chain = true) @Accessors(chain = true)
@TableName("sys_email_users") @TableName("sys_email_users")
@Schema(name = "EmailUsers对象", title = "邮箱发送表", description = "邮箱发送表") @Schema(name = "EmailUsers对象", title = "邮箱发送表", description = "邮箱发送表")
open class EmailUsers : BaseEntity() { open class EmailUsers(
@Schema(name = "email", title = "邮箱") @Schema(name = "email", title = "邮箱")
var email: String? = null var email: String? = null,
@Schema(name = "emailTemplate", title = "使用邮件模板") @Schema(name = "emailTemplate", title = "使用邮件模板")
var emailTemplate: Long? = null var emailTemplate: Long? = null,
@Schema(name = "password", title = "密码") @Schema(name = "password", title = "密码")
var password: String? = null var password: String? = null,
@Schema(name = "host", title = "Host地址") @Schema(name = "host", title = "Host地址")
var host: String? = null var host: String? = null,
@Schema(name = "port", title = "端口号") @Schema(name = "port", title = "端口号")
var port: Int? = null var port: Int? = null,
@Schema(name = "smtpAgreement", title = "邮箱协议") @Schema(name = "smtpAgreement", title = "邮箱协议")
var smtpAgreement: String? = null var smtpAgreement: String? = null,
@Schema(name = "isDefault", title = "是否为默认邮件") @Schema(name = "isDefault", title = "是否为默认邮件")
var isDefault: Byte? = null var isDefault: Byte? = null,
} ) : BaseEntity()

View File

@ -1,52 +0,0 @@
package cn.bunny.dao.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 系统菜单图标
* </p>
*
* @author Bunny
* @since 2024-09-26
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("sys_menu_icon")
@ApiModel(value = "MenuIcon对象", description = "系统菜单图标")
public class MenuIcon implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("icon 名称")
private String iconName;
@ApiModelProperty("创建用户")
private Long createUser;
@ApiModelProperty("操作用户")
private Long updateUser;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("是否删除")
private Byte isDeleted;
}

View File

@ -1,71 +0,0 @@
package cn.bunny.dao.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 系统菜单表
* </p>
*
* @author Bunny
* @since 2024-09-26
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("sys_router")
@ApiModel(value = "Router对象", description = "系统菜单表")
public class Router implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("在项目中路径")
private String routerPath;
@ApiModelProperty("路由名称")
private String routeName;
@ApiModelProperty("父级id")
private Long parentId;
@ApiModelProperty("路由title")
private String title;
@ApiModelProperty("图标")
private String icon;
@ApiModelProperty("等级")
private Integer routerRank;
@ApiModelProperty("是否显示")
private Boolean visible;
@ApiModelProperty("创建用户")
private Long createUser;
@ApiModelProperty("操作用户")
private Long updateUser;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("是否删除")
private Byte isDeleted;
}

View File

@ -3,21 +3,19 @@ package cn.bunny.dao.vo.email
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import lombok.AllArgsConstructor import lombok.AllArgsConstructor
import lombok.Builder import lombok.Builder
import lombok.Data
import lombok.NoArgsConstructor import lombok.NoArgsConstructor
@Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
@Schema(name = "EmailTemplateVo对象", title = "邮箱模板返回内容", description = "邮箱模板返回内容") @Schema(name = "EmailTemplateVo对象", title = "邮箱模板返回内容", description = "邮箱模板返回内容")
class EmailTemplateVo { data class EmailTemplateVo(
@Schema(name = "templateName", title = "模板名称") @Schema(name = "templateName", title = "模板名称")
var templateName: String? = null var templateName: String? = null,
@Schema(name = "subject", title = "主题") @Schema(name = "subject", title = "主题")
var subject: String? = null var subject: String? = null,
@Schema(name = "body", title = "邮件内容") @Schema(name = "body", title = "邮件内容")
var body: String? = null var body: String? = null,
} )

View File

@ -2,57 +2,63 @@ package cn.bunny.dao.vo.user
import cn.bunny.dao.vo.BaseVo import cn.bunny.dao.vo.BaseVo
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import lombok.* import lombok.AllArgsConstructor
import lombok.Builder
import lombok.NoArgsConstructor
/** /**
* 用户登录返回内容 * 用户登录返回内容
*/ */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
@Schema(name = "LoginVo对象", title = "登录成功返回内容", description = "登录成功返回内容") @Schema(name = "LoginVo对象", title = "登录成功返回内容", description = "登录成功返回内容")
class LoginVo : BaseVo() { data class LoginVo(
@Schema(name = "username", title = "用户名") @Schema(name = "username", title = "用户名")
var username: String? = null var username: String? = null,
@Schema(name = "nickName", title = "昵称") @Schema(name = "nickName", title = "昵称")
var nickName: String? = null var nickName: String? = null,
@Schema(name = "email", title = "邮箱") @Schema(name = "email", title = "邮箱")
var email: String? = null var email: String? = null,
@Schema(name = "phone", title = "手机号") @Schema(name = "phone", title = "手机号")
var phone: String? = null var phone: String? = null,
@Schema(name = "password", title = "密码") @Schema(name = "password", title = "密码")
var password: String? = null var password: String? = null,
@Schema(name = "avatar", title = "头像") @Schema(name = "avatar", title = "头像")
var avatar: String? = null var avatar: String? = null,
@Schema(name = "sex", title = "性别", description = "0:女 1:男") @Schema(name = "sex", title = "性别", description = "0:女 1:男")
var sex: Byte? = null var sex: Byte? = null,
@Schema(name = "summary", title = "个人描述") @Schema(name = "summary", title = "个人描述")
var summary: String? = null var summary: String? = null,
@Schema(name = "lastLoginIp", title = "最后登录IP") @Schema(name = "lastLoginIp", title = "最后登录IP")
var lastLoginIp: String? = null var lastLoginIp: String? = null,
@Schema(name = "lastLoginIpAddress", title = "最后登录ip归属地") @Schema(name = "lastLoginIpAddress", title = "最后登录ip归属地")
var lastLoginIpAddress: String? = null var lastLoginIpAddress: String? = null,
@Schema(name = "status", title = "状态", description = "1:禁用 0:正常") @Schema(name = "status", title = "状态", description = "1:禁用 0:正常")
var status: Byte? = null var status: Byte? = null,
@Schema(name = "token", title = "令牌") @Schema(name = "token", title = "令牌")
var token: String? = null var token: String? = null,
@Schema(name = "refreshToken", title = "刷新token")
var refreshToken: String? = null,
@Schema(name = "expires", title = "过期时间")
var expires: Long? = null,
@Schema(name = "roleList", title = "角色列表") @Schema(name = "roleList", title = "角色列表")
var roleList: List<String>? = null var roleList: List<String>? = null,
@Schema(name = "powerList", title = "权限列表") @Schema(name = "powerList", title = "权限列表")
var powerList: List<String>? = null var powerList: List<String>? = null,
} ) : BaseVo()

View File

@ -11,10 +11,10 @@ import lombok.NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Schema(name = "ValidateCodeVo", title = "验证码响应结果实体类", description = "验证码响应结果实体类") @Schema(name = "ValidateCodeVo", title = "验证码响应结果实体类", description = "验证码响应结果实体类")
class ValidateCodeVo { class ValidateCodeVo(
@Schema(name = "codeKey", title = "验证码key") @Schema(name = "codeKey", title = "验证码key")
var codeKey: String? = null var codeKey: String? = null,
@Schema(name = "codeValue", title = "验证码value") @Schema(name = "codeValue", title = "验证码value")
var codeValue: String? = null var codeValue: String? = null,
} )

View File

@ -39,6 +39,10 @@
<artifactId>common-service</artifactId> <artifactId>common-service</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- spring-security --> <!-- spring-security -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -49,15 +53,6 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId> <artifactId>spring-security-test</artifactId>
</dependency> </dependency>
<!-- amqp -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId> <groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId> <artifactId>jackson-dataformat-xml</artifactId>
@ -72,11 +67,6 @@
<groupId>org.aspectj</groupId> <groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId> <artifactId>aspectjweaver</artifactId>
</dependency> </dependency>
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 多数据库源插件 --> <!-- 多数据库源插件 -->
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>

View File

@ -3,13 +3,15 @@ package cn.bunny.services.factory
import cn.bunny.common.service.utils.JwtHelper import cn.bunny.common.service.utils.JwtHelper
import cn.bunny.common.service.utils.ip.IpUtil import cn.bunny.common.service.utils.ip.IpUtil
import cn.bunny.dao.entity.system.AdminUser import cn.bunny.dao.entity.system.AdminUser
import cn.bunny.dao.entity.system.Power
import cn.bunny.dao.entity.system.Role
import cn.bunny.dao.pojo.constant.RedisUserConstant.Companion.getAdminLoginInfoPrefix import cn.bunny.dao.pojo.constant.RedisUserConstant.Companion.getAdminLoginInfoPrefix
import cn.bunny.dao.pojo.constant.RedisUserConstant.Companion.getAdminUserEmailCodePrefix import cn.bunny.dao.pojo.constant.RedisUserConstant.Companion.getAdminUserEmailCodePrefix
import cn.bunny.dao.vo.user.LoginVo import cn.bunny.dao.vo.user.LoginVo
import cn.bunny.services.mapper.UserMapper import cn.bunny.services.mapper.PowerMapper
import cn.bunny.services.mapper.RoleMapper
import org.springframework.beans.BeanUtils import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.data.redis.core.RedisTemplate import org.springframework.data.redis.core.RedisTemplate
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
@ -18,17 +20,20 @@ import java.util.concurrent.TimeUnit
@Component @Component
@Transactional @Transactional
class UserFactory { class UserFactory {
@Qualifier("redisTemplate") @Autowired
private lateinit var powerMapper: PowerMapper
@Autowired
private lateinit var roleMapper: RoleMapper
@Autowired @Autowired
private lateinit var redisTemplate: RedisTemplate<Any, Any> private lateinit var redisTemplate: RedisTemplate<Any, Any>
@Autowired
private lateinit var userMapper: UserMapper
fun buildUserVo(user: AdminUser, readMeDay: Long): LoginVo { fun buildUserVo(user: AdminUser, readMeDay: Long): LoginVo {
// 创建token // 创建token
val userId = user.id val userId = user.id!!
val token = JwtHelper.createToken(userId, user.email, readMeDay.toInt()) val email = user.email!!
val token = JwtHelper.createToken(userId, email, readMeDay.toInt())
// 设置用户IP地址并更新用户信息 // 设置用户IP地址并更新用户信息
val updateUser = AdminUser() val updateUser = AdminUser()
@ -40,17 +45,19 @@ class UserFactory {
val loginVo = LoginVo() val loginVo = LoginVo()
BeanUtils.copyProperties(user, loginVo) BeanUtils.copyProperties(user, loginVo)
loginVo.token = token loginVo.token = token
loginVo.refreshToken = token
loginVo.lastLoginIp = IpUtil.getCurrentUserIpAddress().remoteAddr loginVo.lastLoginIp = IpUtil.getCurrentUserIpAddress().remoteAddr
loginVo.lastLoginIpAddress = IpUtil.getCurrentUserIpAddress().ipRegion loginVo.lastLoginIpAddress = IpUtil.getCurrentUserIpAddress().ipRegion
// TODO 设置权限和角色内容 loginVo.roleList = roleMapper.selectListByUserId(userId).map { role: Role -> role.roleCode!! }
loginVo.roleList = listOf("admin", "common") loginVo.powerList = powerMapper.selectListByUserId(userId).map { power: Power -> power.powerCode!! }
loginVo.powerList = listOf("*.*") loginVo.updateUser = userId
loginVo.expires = readMeDay
// 将信息保存在Redis中 // 将信息保存在Redis中
redisTemplate.opsForValue().set(getAdminLoginInfoPrefix(user.email!!), loginVo, readMeDay, TimeUnit.DAYS) redisTemplate.opsForValue().set(getAdminLoginInfoPrefix(email), loginVo, readMeDay, TimeUnit.DAYS)
// 将Redis中验证码删除 // 将Redis中验证码删除
redisTemplate.delete(getAdminUserEmailCodePrefix(user.email!!)) redisTemplate.delete(getAdminUserEmailCodePrefix(email))
return loginVo return loginVo
} }

View File

@ -29,22 +29,22 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher
@EnableMethodSecurity @EnableMethodSecurity
class WebSecurityConfig { class WebSecurityConfig {
@Autowired @Autowired
private val redisTemplate: RedisTemplate<Any, Any>? = null private lateinit var redisTemplate: RedisTemplate<Any, Any?>
// 自定义用户接口 // 自定义用户接口
@Autowired @Autowired
private val customUserDetailsService: CustomUserDetailsService? = null private lateinit var customUserDetailsService: CustomUserDetailsService
// 自定义密码加密器 // 自定义密码加密器
@Autowired @Autowired
private val customPasswordEncoder: CustomPasswordEncoder? = null private lateinit var customPasswordEncoder: CustomPasswordEncoder
// 自定义验证码 // 自定义验证码
@Autowired @Autowired
private val customAuthorizationManager: CustomAuthorizationManagerServiceImpl? = null private lateinit var customAuthorizationManager: CustomAuthorizationManagerServiceImpl
@Autowired @Autowired
private val authenticationConfiguration: AuthenticationConfiguration? = null private lateinit var authenticationConfiguration: AuthenticationConfiguration
@Bean @Bean
@Throws(Exception::class) @Throws(Exception::class)
@ -71,13 +71,12 @@ class WebSecurityConfig {
exception.accessDeniedHandler(SecurityAccessDeniedHandler()) exception.accessDeniedHandler(SecurityAccessDeniedHandler())
} // 登录验证过滤器 } // 登录验证过滤器
.addFilterBefore( .addFilterBefore(
TokenLoginFilterService(authenticationConfiguration!!, redisTemplate!!, customUserDetailsService!!), TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService),
UsernamePasswordAuthenticationFilter::class.java UsernamePasswordAuthenticationFilter::class.java
) // 其它权限鉴权过滤器 )
.addFilterAt( // 其它权限鉴权过滤器
TokenAuthenticationFilter(redisTemplate), .addFilterAt(TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter::class.java)
UsernamePasswordAuthenticationFilter::class.java // 自定义密码加密器和用户登录
) // 自定义密码加密器和用户登录
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService) .passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService)
return httpSecurity.build() return httpSecurity.build()

View File

@ -13,7 +13,7 @@ import org.springframework.web.filter.OncePerRequestFilter
import java.io.IOException import java.io.IOException
import java.util.function.Consumer 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") val token = request.getHeader("token")

View File

@ -31,10 +31,10 @@ import java.util.*
*/ */
class TokenLoginFilterService( class TokenLoginFilterService(
authenticationConfiguration: AuthenticationConfiguration, authenticationConfiguration: AuthenticationConfiguration,
redisTemplate: RedisTemplate<Any, Any>, redisTemplate: RedisTemplate<Any, Any?>,
customUserDetailsService: CustomUserDetailsService customUserDetailsService: CustomUserDetailsService,
) : UsernamePasswordAuthenticationFilter() { ) : UsernamePasswordAuthenticationFilter() {
private val redisTemplate: RedisTemplate<Any, Any> private val redisTemplate: RedisTemplate<Any, Any?>
private val customUserDetailsService: CustomUserDetailsService private val customUserDetailsService: CustomUserDetailsService
private lateinit var loginDto: LoginDto private lateinit var loginDto: LoginDto
@ -66,11 +66,17 @@ class TokenLoginFilterService(
val password = loginDto.password val password = loginDto.password
// 获取Redis中邮箱验证码并判断是否存在或过期 // 获取Redis中邮箱验证码并判断是否存在或过期
val redisEmailCode = redisTemplate.opsForValue()[getAdminUserEmailCodePrefix(username!!)] val redisEmailCode = redisTemplate.opsForValue().get(getAdminUserEmailCodePrefix(username!!))
redisEmailCode ?: out(response, Result.error(ResultCodeEnum.EMAIL_CODE_EMPTY)) if (redisEmailCode == null) {
out(response, Result.error(ResultCodeEnum.EMAIL_CODE_EMPTY))
return null
}
// 判断邮箱验证码是否和用户传入的验证码一致 // 判断邮箱验证码是否和用户传入的验证码一致
if (emailCode != redisEmailCode?.toString()?.lowercase()) out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING)) if (emailCode != redisEmailCode.toString().lowercase()) {
out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING))
return null
}
// 封装对象,将用户名传入 // 封装对象,将用户名传入
val authenticationToken: Authentication = UsernamePasswordAuthenticationToken(username, password) val authenticationToken: Authentication = UsernamePasswordAuthenticationToken(username, password)
@ -103,7 +109,7 @@ class TokenLoginFilterService(
override fun unsuccessfulAuthentication( override fun unsuccessfulAuthentication(
request: HttpServletRequest, request: HttpServletRequest,
response: HttpServletResponse, response: HttpServletResponse,
failed: AuthenticationException failed: AuthenticationException,
) { ) {
val password = loginDto.password val password = loginDto.password
val username = loginDto.username val username = loginDto.username

View File

@ -3,9 +3,11 @@ package cn.bunny.services.security.service.impl
import cn.bunny.common.service.exception.BunnyException import cn.bunny.common.service.exception.BunnyException
import cn.bunny.dao.dto.system.LoginDto import cn.bunny.dao.dto.system.LoginDto
import cn.bunny.dao.entity.system.AdminUser import cn.bunny.dao.entity.system.AdminUser
import cn.bunny.dao.entity.system.Role
import cn.bunny.dao.pojo.result.ResultCodeEnum import cn.bunny.dao.pojo.result.ResultCodeEnum
import cn.bunny.dao.vo.user.LoginVo import cn.bunny.dao.vo.user.LoginVo
import cn.bunny.services.factory.UserFactory import cn.bunny.services.factory.UserFactory
import cn.bunny.services.mapper.RoleMapper
import cn.bunny.services.mapper.UserMapper import cn.bunny.services.mapper.UserMapper
import cn.bunny.services.security.custom.CustomUser import cn.bunny.services.security.custom.CustomUser
import cn.bunny.services.security.service.CustomUserDetailsService import cn.bunny.services.security.service.CustomUserDetailsService
@ -19,26 +21,27 @@ import org.springframework.util.DigestUtils
@Component @Component
class CustomUserDetailsServiceImpl : CustomUserDetailsService { class CustomUserDetailsServiceImpl : CustomUserDetailsService {
@Autowired
private lateinit var roleMapper: RoleMapper
@Autowired @Autowired
private lateinit var userFactory: UserFactory private lateinit var userFactory: UserFactory
@Autowired @Autowired
private lateinit var userMapper: UserMapper private lateinit var userMapper: UserMapper
@Throws(UsernameNotFoundException::class) @Throws(UsernameNotFoundException::class)
override fun loadUserByUsername(username: String): UserDetails { override fun loadUserByUsername(username: String): UserDetails {
// 查询用户相关内容 // 查询用户相关内容
val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username) val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username).or().eq(AdminUser::username, username)
.or()
.eq(AdminUser::username, username)
// 根据邮箱查询用户名 // 根据邮箱查询用户名
val user = userMapper.selectOne(queryWrapper) val user = userMapper.selectOne(queryWrapper)
user ?: throw UsernameNotFoundException("") user ?: throw UsernameNotFoundException("用户不存在 ")
// TODO 查询所有的角色 // 根据用户id查询当前用户所有角色
return CustomUser(user, AuthorityUtils.createAuthorityList(listOf("admin", "common"))) val roleList: List<Role> = roleMapper.selectListByUserId(user.id!!)
return CustomUser(user, AuthorityUtils.createAuthorityList(roleList.map { role -> role.roleCode }))
} }
/** /**
@ -48,8 +51,7 @@ class CustomUserDetailsServiceImpl : CustomUserDetailsService {
* @return 登录后结果返回 * @return 登录后结果返回
*/ */
override fun login(loginDto: LoginDto): LoginVo { override fun login(loginDto: LoginDto): LoginVo {
val username = loginDto.username val (username, password, _, readMeDay) = loginDto
val password = loginDto.password
// 查询用户相关内容 // 查询用户相关内容
val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username).or() val queryWrapper = KtQueryWrapper(AdminUser()).eq(AdminUser::email, username).or()
@ -60,6 +62,6 @@ class CustomUserDetailsServiceImpl : CustomUserDetailsService {
val md5Password: String = DigestUtils.md5DigestAsHex(password!!.byteInputStream()) val md5Password: String = DigestUtils.md5DigestAsHex(password!!.byteInputStream())
if (!user.password.equals(md5Password)) throw BunnyException(ResultCodeEnum.LOGIN_ERROR) if (!user.password.equals(md5Password)) throw BunnyException(ResultCodeEnum.LOGIN_ERROR)
return userFactory.buildUserVo(user, loginDto.readMeDay) return userFactory.buildUserVo(user, readMeDay)
} }
} }