diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
index 3883e656..38674041 100644
--- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
+++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
@@ -77,6 +77,7 @@ public class SecurityConfig {
// .requestMatchers("/threedroamb/**").permitAll()
// .requestMatchers("/overview/**").permitAll()
.requestMatchers("/wt/**").permitAll()
+ .requestMatchers("/system/acctPasswordPolicy/**").permitAll()
.requestMatchers("/fb/**").permitAll()
// .requestMatchers("/base/**").permitAll()
// .requestMatchers("/zq/**").permitAll()
diff --git a/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java b/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java
new file mode 100644
index 00000000..4c7bc27f
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java
@@ -0,0 +1,139 @@
+package com.yfd.platform.system.controller;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.yfd.platform.common.DataSourceRequest;
+import com.yfd.platform.config.ResponseResult;
+import com.yfd.platform.system.domain.SysAcctPasswordPolicy;
+import com.yfd.platform.system.service.ISysAcctPasswordPolicyService;
+import com.yfd.platform.system.service.IUserService;
+import com.yfd.platform.utils.DataSourceRequestUtil;
+import com.yfd.platform.utils.SecurityUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 账号密码策略 前端控制器
+ *
+ */
+@Slf4j
+@RestController
+@RequestMapping("/system/acctPasswordPolicy")
+@Tag(name = "账号密码策略管理")
+public class SysAcctPasswordPolicyController {
+
+ @Resource
+ private ISysAcctPasswordPolicyService policyService;
+
+ @Resource
+ private IUserService userService;
+
+ @GetMapping("/current")
+ @Operation(summary = "获取当前生效的密码策略")
+ public ResponseResult current() {
+ SysAcctPasswordPolicy policy = policyService.getCurrentPolicy();
+ return policy == null
+ ? ResponseResult.error("未配置密码策略")
+ : ResponseResult.successData(policy);
+ }
+
+ @GetMapping("/getById")
+ @Operation(summary = "根据ID查询密码策略")
+ public ResponseResult getById(@RequestParam String id) {
+ SysAcctPasswordPolicy policy = policyService.getById(id);
+ return policy == null
+ ? ResponseResult.error("策略不存在")
+ : ResponseResult.successData(policy);
+ }
+
+ @PostMapping("/queryPageList")
+ @Operation(summary = "分页查询密码策略列表")
+ public ResponseResult queryPageList(@RequestBody DataSourceRequest request) {
+ Page page = DataSourceRequestUtil.executeQuery(request, SysAcctPasswordPolicy.class, policyService);
+ return ResponseResult.successData(page);
+ }
+
+ @PostMapping("/list")
+ @Operation(summary = "查询密码策略列表(不分页)")
+ public ResponseResult list(@RequestBody DataSourceRequest request) {
+ List list = DataSourceRequestUtil.executeList(request, SysAcctPasswordPolicy.class, policyService);
+ return ResponseResult.successData(list);
+ }
+
+ @PostMapping("/add")
+ @Operation(summary = "新增密码策略")
+ public ResponseResult add(@RequestBody SysAcctPasswordPolicy policy) {
+ if (StrUtil.isBlank(policy.getName())) {
+ return ResponseResult.error("策略名称不能为空");
+ }
+ policy.setId(IdUtil.fastSimpleUUID());
+// policy.setRecordUser(SecurityUtils.getUserId());
+ policy.setRecordUser("admin");
+ policy.setRecordTime(new Date());
+ policy.setIsDeleted(0);
+
+ boolean ok = policyService.save(policy);
+ return ok ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败");
+ }
+
+ @PostMapping("/update")
+ @Operation(summary = "修改密码策略")
+ public ResponseResult update(@RequestBody SysAcctPasswordPolicy policy) {
+ if (StrUtil.isBlank(policy.getId())) {
+ return ResponseResult.error("ID不能为空");
+ }
+ SysAcctPasswordPolicy exist = policyService.getById(policy.getId());
+ if (exist == null) {
+ return ResponseResult.error("策略不存在");
+ }
+ policy.setModifyUser(userService.getUsername());
+ policy.setModifyTime(new Date());
+
+ boolean ok = policyService.updateById(policy);
+ return ok ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败");
+ }
+
+ @PostMapping("/delete")
+ @Operation(summary = "删除密码策略(软删除)")
+ public ResponseResult delete(@RequestBody List ids) {
+ if (ids == null || ids.isEmpty()) {
+ return ResponseResult.error("ID不能为空");
+ }
+ Date now = new Date();
+ String username = userService.getUsername();
+ for (String id : ids) {
+ SysAcctPasswordPolicy policy = policyService.getById(id);
+ if (policy != null) {
+ policy.setIsDeleted(1);
+ policy.setDeleteUser(username);
+ policy.setDeleteTime(now);
+ policyService.updateById(policy);
+ }
+ }
+ return ResponseResult.success("删除成功");
+ }
+
+ @PostMapping("/validatePassword")
+ @Operation(summary = "根据当前策略校验密码复杂度")
+ public ResponseResult validatePassword(@RequestParam String password,
+ @RequestParam(required = false) String username) {
+ SysAcctPasswordPolicy policy = policyService.getCurrentPolicy();
+ if (policy == null) {
+ return ResponseResult.error("未配置密码策略");
+ }
+ String errMsg = policyService.validatePassword(policy, password, username);
+ if (errMsg != null) {
+ return ResponseResult.error(errMsg);
+ }
+ return ResponseResult.success("密码校验通过");
+ }
+}
diff --git a/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java b/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java
new file mode 100644
index 00000000..86c838e0
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java
@@ -0,0 +1,189 @@
+package com.yfd.platform.system.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ *
+ * 账号密码策略表
+ *
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("SYS_ACCT_PASSWORD_POLICY")
+public class SysAcctPasswordPolicy implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /** 主键ID */
+ @TableId(type = IdType.ASSIGN_UUID)
+ private String id;
+
+ /** 密码策略标识 */
+ private String code;
+
+ /** 策略名称 */
+ private String name;
+
+ /** 用户名敏感性校验 */
+ private Integer usernameSensitiveValid;
+
+ /** 密码敏感性校验 */
+ private Integer passwordSensitiveValid;
+
+ /** 启用短信重置密码 */
+ private Integer enableSmsResetPwd;
+
+ /** 启用邮箱重置密码 */
+ private Integer enableEmailResetPwd;
+
+ /** 启用输入密码 */
+ private Integer enableInputPassword;
+
+ /** 启用默认密码 */
+ private Integer enableDefaultPassword;
+
+ /** 默认密码 */
+ private String defaultPassword;
+
+ /** 密码最小长度 */
+ private Integer minLength;
+
+ /** 密码最大长度 */
+ private Integer maxLength;
+
+ /** 最大密码错误次数 */
+ private Integer maxErrorNumber;
+
+ /** 密码必须包含字符类型 */
+ private String passwordCharsRequire;
+
+ /** 密码数字数量要求 */
+ private Integer digitsCount;
+
+ /** 密码小写字母数量要求 */
+ private Integer lowercaseCount;
+
+ /** 密码大写字母数量要求 */
+ private Integer uppercaseCount;
+
+ /** 特殊字符数量要求 */
+ private Integer specialCharCount;
+
+ /** 密码不可与用户名相同 */
+ private Integer notUsername;
+
+ /** 密码正则表达式 */
+ private String regularExpression;
+
+ /** 不可使用最近N次密码 */
+ private Integer notRecentCount;
+
+ /** 启用密码策略 */
+ private Integer enablePasswordPolicy;
+
+ /** 启用安全策略 */
+ private Integer enableSecurityPolicy;
+
+ /** 启用账户锁定 */
+ private Integer enableLock;
+
+ /** 锁定时长(秒) */
+ private Integer lockedExpireTime;
+
+ /** 启用验证码 */
+ private Integer enableCaptcha;
+
+ /** 验证码类型 */
+ private String captureType;
+
+ /** 触发验证码的错误次数 */
+ private Integer maxCheckCaptcha;
+
+ /** Web端多端登录 */
+ private Integer enableWebMultipleLogin;
+
+ /** 移动端多端登录 */
+ private Integer enableAppMultipleLogin;
+
+ /** 密码更新频率(天) */
+ private Integer passwordUpdateRate;
+
+ /** 规则变更时强制修改密码 */
+ private Integer forceModifyPwdRuleModify;
+
+ /** 密码修改提醒周期(天) */
+ private Integer passwordReminderPeriod;
+
+ /** 首次登录强制修改密码 */
+ private Integer forceModifyPassword;
+
+ /** 允许账号登录 */
+ private Integer enableAccountLogin;
+
+ /** 修改密码后需重新登录 */
+ private Integer loginAgain;
+
+ /** 允许短信登录 */
+ private Integer enableSmsLogin;
+
+ /** 启用随机密码 */
+ private Integer enableRandomPassword;
+
+ /** 启用数据加密 */
+ private Integer enableDataSecurity;
+
+ /** 是否全局策略 */
+ private Integer isBelongGlobal;
+
+ /** 是否双重验证 */
+ private Integer isTwoFactorAuth;
+
+ /** 创建人 */
+ @TableField(fill = FieldFill.INSERT)
+ private String recordUser;
+
+ /** 创建时间 */
+ @TableField(fill = FieldFill.INSERT)
+ private Date recordTime;
+
+ /** 修改人 */
+ @TableField(fill = FieldFill.UPDATE)
+ private String modifyUser;
+
+ /** 修改时间 */
+ @TableField(fill = FieldFill.UPDATE)
+ private Date modifyTime;
+
+ /** 是否已删除 0=未删除 1=已删除 */
+ @TableLogic
+ private Integer isDeleted;
+
+ /** 删除人 */
+ private String deleteUser;
+
+ /** 删除时间 */
+ private Date deleteTime;
+
+ /** 过滤内容 */
+ private String filterContent;
+
+ /** 排序 */
+ private Integer orderIndex;
+
+ /** 启用验证码类型 */
+ private String enableCaptchaType;
+
+ /** 启用企业微信登录 */
+ private Integer enableEnterpriseWechatLogin;
+
+ /** 启用钉钉登录 */
+ private Integer enableDingdingLogin;
+
+ /** 启用微信登录 */
+ private Integer enableWechatLogin;
+}
diff --git a/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java b/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java
new file mode 100644
index 00000000..b89fb6e7
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java
@@ -0,0 +1,14 @@
+package com.yfd.platform.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yfd.platform.system.domain.SysAcctPasswordPolicy;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ *
+ * 账号密码策略表 Mapper 接口
+ *
+ */
+@Mapper
+public interface SysAcctPasswordPolicyMapper extends BaseMapper {
+}
diff --git a/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java b/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java
new file mode 100644
index 00000000..eaa81b98
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java
@@ -0,0 +1,26 @@
+package com.yfd.platform.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yfd.platform.system.domain.SysAcctPasswordPolicy;
+
+/**
+ *
+ * 账号密码策略表 服务类
+ *
+ */
+public interface ISysAcctPasswordPolicyService extends IService {
+
+ /**
+ * 获取当前生效的策略(取排序最小且未删除的那条)
+ */
+ SysAcctPasswordPolicy getCurrentPolicy();
+
+ /**
+ * 根据策略校验密码复杂度
+ *
+ * @param password 待校验的密码
+ * @param username 关联的用户名(用于NOT_USERNAME校验)
+ * @return null=校验通过,否则返回错误提示
+ */
+ String validatePassword(SysAcctPasswordPolicy policy, String password, String username);
+}
diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java
new file mode 100644
index 00000000..2c4f569b
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java
@@ -0,0 +1,95 @@
+package com.yfd.platform.system.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yfd.platform.system.domain.SysAcctPasswordPolicy;
+import com.yfd.platform.system.mapper.SysAcctPasswordPolicyMapper;
+import com.yfd.platform.system.service.ISysAcctPasswordPolicyService;
+import org.springframework.stereotype.Service;
+
+import java.util.regex.Pattern;
+
+/**
+ *
+ * 账号密码策略表 服务实现类
+ *
+ */
+@Service
+public class SysAcctPasswordPolicyServiceImpl extends ServiceImpl
+ implements ISysAcctPasswordPolicyService {
+
+ @Override
+ public SysAcctPasswordPolicy getCurrentPolicy() {
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+ wrapper.eq(SysAcctPasswordPolicy::getIsDeleted, 0)
+ .eq(SysAcctPasswordPolicy::getEnablePasswordPolicy, 1)
+ .orderByAsc(SysAcctPasswordPolicy::getOrderIndex)
+ .last("LIMIT 1");
+ return getOne(wrapper);
+ }
+
+ @Override
+ public String validatePassword(SysAcctPasswordPolicy policy, String password, String username) {
+ if (policy == null || StrUtil.isBlank(password)) {
+ return "密码不能为空";
+ }
+
+ // 1. 密码长度校验
+ if (policy.getMinLength() != null && password.length() < policy.getMinLength()) {
+ return "密码长度不能少于" + policy.getMinLength() + "位";
+ }
+ if (policy.getMaxLength() != null && password.length() > policy.getMaxLength()) {
+ return "密码长度不能超过" + policy.getMaxLength() + "位";
+ }
+
+ // 2. 密码与用户名不可相同
+ if (isEnabled(policy.getNotUsername()) && StrUtil.isNotBlank(username) && username.equals(password)) {
+ return "密码不能与用户名相同";
+ }
+
+ // 3. 字符类型数量校验
+ int digits = 0, lowercase = 0, uppercase = 0, special = 0;
+ for (char c : password.toCharArray()) {
+ if (Character.isDigit(c)) {
+ digits++;
+ } else if (Character.isLowerCase(c)) {
+ lowercase++;
+ } else if (Character.isUpperCase(c)) {
+ uppercase++;
+ } else {
+ special++;
+ }
+ }
+
+ if (policy.getDigitsCount() != null && digits < policy.getDigitsCount()) {
+ return "密码至少包含" + policy.getDigitsCount() + "个数字";
+ }
+ if (policy.getLowercaseCount() != null && lowercase < policy.getLowercaseCount()) {
+ return "密码至少包含" + policy.getLowercaseCount() + "个小写字母";
+ }
+ if (policy.getUppercaseCount() != null && uppercase < policy.getUppercaseCount()) {
+ return "密码至少包含" + policy.getUppercaseCount() + "个大写字母";
+ }
+ if (policy.getSpecialCharCount() != null && special < policy.getSpecialCharCount()) {
+ return "密码至少包含" + policy.getSpecialCharCount() + "个特殊字符";
+ }
+
+ // 4. 正则表达式校验
+ if (StrUtil.isNotBlank(policy.getRegularExpression())) {
+ try {
+ if (!Pattern.matches(policy.getRegularExpression(), password)) {
+ return "密码格式不符合要求";
+ }
+ } catch (Exception e) {
+ // 正则不合法则跳过
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isEnabled(Integer value) {
+ return value != null && value == 1;
+ }
+}