diff --git a/sql/dm/ruoyi-vue-pro-dm8.sql b/sql/dm/ruoyi-vue-pro-dm8.sql index 0cf97945a..7c5b26b81 100644 --- a/sql/dm/ruoyi-vue-pro-dm8.sql +++ b/sql/dm/ruoyi-vue-pro-dm8.sql @@ -4074,6 +4074,7 @@ CREATE TABLE system_user_role ( id bigint NOT NULL PRIMARY KEY IDENTITY, user_id bigint NOT NULL, role_id bigint NOT NULL, + dept_id bigint NOT NULL, creator varchar(64) DEFAULT '' NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP NULL, updater varchar(64) DEFAULT '' NULL, @@ -4085,6 +4086,7 @@ CREATE TABLE system_user_role ( COMMENT ON COLUMN system_user_role.id IS '自增编号'; COMMENT ON COLUMN system_user_role.user_id IS '用户ID'; COMMENT ON COLUMN system_user_role.role_id IS '角色ID'; +COMMENT ON COLUMN system_user_role.dept_id IS '部门ID'; COMMENT ON COLUMN system_user_role.creator IS '创建者'; COMMENT ON COLUMN system_user_role.create_time IS '创建时间'; COMMENT ON COLUMN system_user_role.updater IS '更新者'; diff --git a/sql/kingbase/ruoyi-vue-pro.sql b/sql/kingbase/ruoyi-vue-pro.sql index 37f3b9b66..6283d85a5 100644 --- a/sql/kingbase/ruoyi-vue-pro.sql +++ b/sql/kingbase/ruoyi-vue-pro.sql @@ -4339,6 +4339,7 @@ CREATE TABLE system_user_role id int8 NOT NULL, user_id int8 NOT NULL, role_id int8 NOT NULL, + dept_id int8 NOT NULL, creator varchar(64) NULL DEFAULT '', create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP, updater varchar(64) NULL DEFAULT '', @@ -4353,6 +4354,7 @@ ALTER TABLE system_user_role COMMENT ON COLUMN system_user_role.id IS '自增编号'; COMMENT ON COLUMN system_user_role.user_id IS '用户ID'; COMMENT ON COLUMN system_user_role.role_id IS '角色ID'; +COMMENT ON COLUMN system_user_role.dept_id IS '部门ID'; COMMENT ON COLUMN system_user_role.creator IS '创建者'; COMMENT ON COLUMN system_user_role.create_time IS '创建时间'; COMMENT ON COLUMN system_user_role.updater IS '更新者'; diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 0c810bef8..264b17894 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -3581,6 +3581,7 @@ CREATE TABLE `system_user_role` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增编号', `user_id` bigint NOT NULL COMMENT '用户ID', `role_id` bigint NOT NULL COMMENT '角色ID', + `dept_id` bigint NOT NULL COMMENT '部门ID', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql index 9fbf8d5ad..07264f5fc 100644 --- a/sql/oracle/ruoyi-vue-pro.sql +++ b/sql/oracle/ruoyi-vue-pro.sql @@ -4218,6 +4218,7 @@ CREATE TABLE system_user_role id number NOT NULL, user_id number NOT NULL, role_id number NOT NULL, + dept_id number NOT NULL, creator varchar2(64) DEFAULT '' NULL, create_time date DEFAULT CURRENT_TIMESTAMP NULL, updater varchar2(64) DEFAULT '' NULL, @@ -4232,6 +4233,7 @@ ALTER TABLE system_user_role COMMENT ON COLUMN system_user_role.id IS '自增编号'; COMMENT ON COLUMN system_user_role.user_id IS '用户ID'; COMMENT ON COLUMN system_user_role.role_id IS '角色ID'; +COMMENT ON COLUMN system_user_role.dept_id IS '部门ID'; COMMENT ON COLUMN system_user_role.creator IS '创建者'; COMMENT ON COLUMN system_user_role.create_time IS '创建时间'; COMMENT ON COLUMN system_user_role.updater IS '更新者'; diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql index 9368057ff..b2e0527fd 100644 --- a/sql/sqlserver/ruoyi-vue-pro.sql +++ b/sql/sqlserver/ruoyi-vue-pro.sql @@ -10352,6 +10352,7 @@ CREATE TABLE system_user_role id bigint NOT NULL PRIMARY KEY IDENTITY, user_id bigint NOT NULL, role_id bigint NOT NULL, + dept_id bigint NOT NULL, creator nvarchar(64) DEFAULT '' NULL, create_time datetime2 DEFAULT CURRENT_TIMESTAMP NULL, updater nvarchar(64) DEFAULT '' NULL, @@ -10382,6 +10383,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'role_id' GO +EXEC sp_addextendedproperty + 'MS_Description', N'部门ID', + 'SCHEMA', N'dbo', + 'TABLE', N'system_user_role', + 'COLUMN', N'dept_id' +GO + EXEC sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', N'dbo', diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 2f92adc0e..cd1698227 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -24,6 +24,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment; @@ -42,6 +43,12 @@ public class FileController { public CommonResult uploadFile(FileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); String path = uploadReqVO.getPath(); + String extname = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")).toLowerCase(); + if(StrUtil.isEmpty(extname)){ + return error(3379,"只能上传图片文件!"); + } + if(!".bmp,.jpg,.jpeg,.png".contains(extname)) + return error(3379,"只能上传图片文件!"); return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java index 463f3bb21..471f79f42 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Pattern; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -28,7 +29,8 @@ public class AppAuthLoginReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; // ========== 绑定社交登录时,需要传递如下参数 ========== diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java index 043c881fd..54e4f5ace 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserResetPasswordReqVO.java @@ -21,7 +21,8 @@ public class AppMemberUserResetPasswordReqVO { @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") @NotEmpty(message = "新密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; @Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java index 5319d727e..a533a6579 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdatePasswordReqVO.java @@ -19,7 +19,8 @@ public class AppMemberUserUpdatePasswordReqVO { @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") @NotEmpty(message = "新密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; @Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index 43b1ea9a4..ca5eb68e4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java @@ -28,7 +28,8 @@ public class AuthLoginReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; // ========== 图片验证码相关 ========== diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java index fb88a077e..89cd9dc19 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java @@ -26,7 +26,8 @@ public class AuthRegisterReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; // ========== 图片验证码相关 ========== diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java index 175afa34b..f496e3526 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java @@ -57,7 +57,8 @@ public class TenantSaveReqVO { private String username; @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; @AssertTrue(message = "用户账号、密码不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java index cfe37f620..3cba12f94 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Pattern; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -12,12 +13,14 @@ public class UserProfileUpdatePasswordReqVO { @Schema(description = "旧密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "旧密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String oldPassword; @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "654321") @NotEmpty(message = "新密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String newPassword; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index bdcbe0a4d..7cadd243f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -67,7 +67,9 @@ public class UserSaveReqVO { // ========== 仅【创建】时,需要传递的字段 ========== @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; @AssertTrue(message = "密码不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java index 065d0d91f..0c2db2f8c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Pattern; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -17,7 +18,9 @@ public class UserUpdatePasswordReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + + @Length(min = 8, max = 16, message = "密码长度为 8-16 位") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$", message = "用户密码由 数字、字母 特殊字符(@#$%^&+=!之一)8-16位组成") private String password; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java index 010184066..317f7aa9a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java @@ -31,5 +31,8 @@ public class UserRoleDO extends BaseDO { * 角色 ID */ private Long roleId; - + /** + * 部门 ID + */ + private Long deptId; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java index c0c9be8e4..0303738b3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java @@ -5,8 +5,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.*; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -47,5 +48,12 @@ public interface AdminUserMapper extends BaseMapperX { default List selectListByDeptIds(Collection deptIds) { return selectList(AdminUserDO::getDeptId, deptIds); } + @Select("SELECT update_time FROM system_user_password_time WHERE user_id = #{userId}") + LocalDateTime getPasswordUpdateRecord(@Param("userId") Long userId); + @Update("UPDATE system_user_password_time SET update_time = CURRENT_TIMESTAMP WHERE user_id = #{userId}") + void update_password_updatetime(@Param("userId") Long userId); + + @Insert("INSERT INTO system_user_password_time(user_id,update_time) values(#{userId},CURRENT_TIMESTAMP)") + void insertPasswordUpdatetime(@Param("userId") Long userId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java index 1cd58306b..7ef57f395 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java @@ -107,4 +107,8 @@ public interface RedisKeyConstants { */ String WXA_SUBSCRIBE_TEMPLATE = "wxa_subscribe_template"; + /** + * 用户登录错误次数 + */ + String LOGIN_ERROR_TIMES = "user_login_error_times"; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java index 136866ca0..2d88b7b65 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.framework.datapermission.config; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer; import org.springframework.context.annotation.Bean; @@ -20,6 +21,7 @@ public class DataPermissionConfiguration { // dept rule.addDeptColumn(AdminUserDO.class); rule.addDeptColumn(DeptDO.class, "id"); + rule.addDeptColumn(UserRoleDO.class); // user rule.addUserColumn(AdminUserDO.class, "id"); }; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index 45b9ee1f5..9eb7adce7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.system.service.auth; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; @@ -14,6 +16,7 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; @@ -31,9 +34,13 @@ import jakarta.annotation.Resource; import jakarta.validation.Validator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Objects; +import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; @@ -64,6 +71,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { private CaptchaService captchaService; @Resource private SmsCodeApi smsCodeApi; + @Resource + private StringRedisTemplate stringRedisTemplate; // WxMpService 需要使用到,所以在 Service 注入了它 /** * 验证码的开关,默认为 true @@ -76,9 +85,30 @@ public class AdminAuthServiceImpl implements AdminAuthService { final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; // 校验账号是否存在 AdminUserDO user = userService.getUserByUsername(username); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime1= userService.getPasswordUpdatetime(user.getId()); + if (ChronoUnit.DAYS.between(localDateTime1, localDateTime) >= 90) { + //密码超过90天未修改 + userService.updateUserStatus(user.getId(), 1); + throw exception(new ErrorCode(-333, "超过90天未修改密码,请联系管理员解锁")); + } + if (user == null) { createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); - throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + //用户登录密码错误次数限制 + String key = RedisKeyConstants.LOGIN_ERROR_TIMES + ":" + user.getTenantId() + ":" + username; + String times = stringRedisTemplate.opsForValue().get(key); + if (StrUtil.isEmpty(times)) { + stringRedisTemplate.opsForValue().increment(key); + stringRedisTemplate.expire(key, 1, TimeUnit.DAYS); //一天内 + } + + long _times = stringRedisTemplate.opsForValue().increment(key); + if (_times >= 6) { + userService.updateUserStatus(user.getId(), 1); + throw exception(new ErrorCode(1_002_000_099, "账号密码不正确次数过多,账号已锁定!")); + } else + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); } if (!userService.isPasswordMatch(password, user.getPassword())) { createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java index 2d9e12fe6..f4acfcdeb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -219,6 +220,8 @@ public class PermissionServiceImpl implements PermissionService { UserRoleDO entity = new UserRoleDO(); entity.setUserId(userId); entity.setRoleId(roleId); + AdminUserDO adminUserDO = userService.getUser(userId); + entity.setDeptId(adminUserDO.getDeptId()); return entity; })); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index 15564408d..eb21177ba 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import jakarta.validation.Valid; import java.io.InputStream; +import java.time.LocalDateTime; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -215,5 +216,20 @@ public interface AdminUserService { * @return 是否匹配 */ boolean isPasswordMatch(String rawPassword, String encodedPassword); + /** + * 取得密码修改的时间 + * @Author atuchina + * @Date 2024/6/18 10:21 + * @param userId + * @return + */ + LocalDateTime getPasswordUpdatetime(Long userId); + /** + * 插入密码修改时间 + * @Author atuchina + * @Date 2024/6/18 10:37 + * @param userId + */ + void insertPasswordUpdatetime(Long userId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index ef06d3c29..833e80d7f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper; import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.dept.PostService; import cn.iocoder.yudao.module.system.service.permission.PermissionService; @@ -37,6 +38,7 @@ import jakarta.annotation.Resource; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -83,6 +85,8 @@ public class AdminUserServiceImpl implements AdminUserService { private FileApi fileApi; @Resource private ConfigApi configApi; + @Resource + private StringRedisTemplate stringRedisTemplate; // WxMpService 需要使用到,所以在 Service 注入了它 @Override @Transactional(rollbackFor = Exception.class) @@ -129,7 +133,7 @@ public class AdminUserServiceImpl implements AdminUserService { // 2. 插入用户 AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class); - user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 + user.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认关闭 user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码 userMapper.insert(user); return user.getId(); @@ -196,6 +200,13 @@ public class AdminUserServiceImpl implements AdminUserService { AdminUserDO updateObj = new AdminUserDO().setId(id); updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码 userMapper.updateById(updateObj); + + //更新密码修改时间表 + if(userMapper.getPasswordUpdateRecord(id)!=null){ + userMapper.update_password_updatetime(id); + }else{ + userMapper.insertPasswordUpdatetime(id); + } } @Override @@ -224,6 +235,7 @@ public class AdminUserServiceImpl implements AdminUserService { updateObj.setPassword(encodePassword(password)); // 加密密码 userMapper.updateById(updateObj); + userMapper.update_password_updatetime(id); // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); LogRecordContext.putVariable("newPassword", updateObj.getPassword()); @@ -232,7 +244,11 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public void updateUserStatus(Long id, Integer status) { // 校验用户存在 - validateUserExists(id); + AdminUserDO oldUser = validateUserExists(id); + if(oldUser.getStatus()==1) {//用户登录错误缓存次数重置 + String key = RedisKeyConstants.LOGIN_ERROR_TIMES + ":" + oldUser.getTenantId() + ":" + oldUser.getUsername(); + stringRedisTemplate.delete(key); + } // 更新状态 AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); @@ -527,5 +543,17 @@ public class AdminUserServiceImpl implements AdminUserService { private String encodePassword(String password) { return passwordEncoder.encode(password); } - + @Override + public LocalDateTime getPasswordUpdatetime(Long userId){ + LocalDateTime localDateTime = userMapper.getPasswordUpdateRecord(userId); + if(localDateTime==null){ + userMapper.insertPasswordUpdatetime(userId); + return LocalDateTime.now(); + }else + return localDateTime; + } + @Override + public void insertPasswordUpdatetime(Long userId){ + userMapper.insertPasswordUpdatetime(userId); + } }