Initial commit
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
spring:
|
||||
application:
|
||||
name: auth-system
|
||||
|
||||
# 环境配置(默认开发环境)
|
||||
profiles:
|
||||
active: dev
|
||||
|
||||
# 数据源配置
|
||||
datasource:
|
||||
url: jdbc:mysql://152.32.168.79:3306/auth?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: auth_user
|
||||
password: auth_pwd
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# HikariCP 连接池配置
|
||||
hikari:
|
||||
# 连接池名称
|
||||
pool-name: AuthSystemHikariCP
|
||||
# 最小空闲连接数
|
||||
minimum-idle: 5
|
||||
# 最大连接数
|
||||
maximum-pool-size: 20
|
||||
# 连接超时时间(毫秒)
|
||||
connection-timeout: 30000
|
||||
# 空闲连接超时时间(毫秒)
|
||||
idle-timeout: 600000
|
||||
# 连接最大存活时间(毫秒)
|
||||
max-lifetime: 1800000
|
||||
# 连接测试查询
|
||||
connection-test-query: SELECT 1
|
||||
|
||||
# Jackson配置
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
|
||||
# Redis配置
|
||||
data:
|
||||
redis:
|
||||
host: 152.32.168.79
|
||||
port: 6379
|
||||
password: 20001201tds
|
||||
database: 0
|
||||
timeout: 3000ms
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8
|
||||
max-idle: 8
|
||||
min-idle: 0
|
||||
max-wait: -1ms
|
||||
|
||||
# 邮件配置
|
||||
mail:
|
||||
host: smtp.qq.com
|
||||
port: 587
|
||||
username: kurihada@qq.com
|
||||
password: objliupbasxvbeig
|
||||
default-encoding: UTF-8
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
required: true
|
||||
ssl:
|
||||
enable: false
|
||||
socketFactory:
|
||||
port: 587
|
||||
class: javax.net.ssl.SSLSocketFactory
|
||||
connectiontimeout: 5000
|
||||
timeout: 5000
|
||||
writetimeout: 5000
|
||||
|
||||
# 服务器配置
|
||||
server:
|
||||
port: 8001
|
||||
|
||||
# JWT配置
|
||||
jwt:
|
||||
secret: authSystemSecretKeyForJWTTokenGenerationAndValidation2024
|
||||
expiration: 3600000 # Access Token: 1小时(毫秒)
|
||||
refresh-expiration: 604800000 # Refresh Token: 7天(毫秒)
|
||||
header: Authorization
|
||||
prefix: Bearer
|
||||
|
||||
# 限流配置
|
||||
rate-limit:
|
||||
# 登录接口限流
|
||||
login:
|
||||
enabled: true
|
||||
window: 60 # 时间窗口:60秒
|
||||
max-requests: 5 # 最大请求次数:5次
|
||||
message: "登录请求过于频繁,请稍后再试"
|
||||
# 注册接口限流
|
||||
register:
|
||||
enabled: true
|
||||
window: 300 # 时间窗口:5分钟
|
||||
max-requests: 3 # 最大请求次数:3次
|
||||
message: "注册请求过于频繁,请稍后再试"
|
||||
# 刷新Token限流
|
||||
refresh:
|
||||
enabled: true
|
||||
window: 60 # 时间窗口:60秒
|
||||
max-requests: 10 # 最大请求次数:10次
|
||||
message: "刷新Token请求过于频繁,请稍后再试"
|
||||
|
||||
# 密码策略配置
|
||||
password:
|
||||
# 最小长度
|
||||
min-length: 8
|
||||
# 最大长度
|
||||
max-length: 32
|
||||
# 是否要求包含小写字母
|
||||
require-lowercase: true
|
||||
# 是否要求包含大写字母
|
||||
require-uppercase: true
|
||||
# 是否要求包含数字
|
||||
require-digit: true
|
||||
# 是否要求包含特殊字符
|
||||
require-special-char: true
|
||||
# 允许的特殊字符
|
||||
special-chars: "!@#$%^&*()_+-=[]{}|;:,.<>?"
|
||||
# 是否禁止常见弱密码
|
||||
forbid-common-passwords: true
|
||||
# 是否禁止包含用户名
|
||||
forbid-username: true
|
||||
# 密码重置token过期时间(秒)- 默认1小时
|
||||
reset-token-expiration: 3600
|
||||
|
||||
# 权限缓存配置
|
||||
permission-cache:
|
||||
# 是否启用权限缓存
|
||||
enabled: true
|
||||
# 用户权限缓存过期时间(秒)- 默认2小时
|
||||
user-permission-ttl: 7200
|
||||
# 角色权限缓存过期时间(秒)- 默认1小时
|
||||
role-permission-ttl: 3600
|
||||
# 用户信息缓存过期时间(秒)- 默认30分钟
|
||||
user-info-ttl: 1800
|
||||
|
||||
# 用户注册配置
|
||||
registration:
|
||||
# 是否为新用户自动分配默认角色
|
||||
auto-assign-default-role: true
|
||||
# 默认角色代码
|
||||
default-role-code: USER
|
||||
# 是否要求邮箱验证(如果为true,未验证邮箱的用户无法登录)
|
||||
require-email-verification: true
|
||||
|
||||
# 邮箱验证配置
|
||||
email:
|
||||
# 验证token过期时间(秒)- 默认24小时
|
||||
verification-token-expiration: 86400
|
||||
|
||||
# 账户锁定配置
|
||||
account-lock:
|
||||
# 最大登录失败次数(默认5次)
|
||||
max-failed-attempts: 5
|
||||
# 账户锁定时长(分钟,默认30分钟)
|
||||
lock-duration-minutes: 30
|
||||
|
||||
# MyBatis Plus配置
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
# 开启驼峰命名映射
|
||||
map-underscore-to-camel-case: true
|
||||
# 日志实现
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
# 主键类型:AUTO-数据库自增
|
||||
id-type: auto
|
||||
# 逻辑删除字段名
|
||||
logic-delete-field: deleted
|
||||
# 逻辑删除值
|
||||
logic-delete-value: 1
|
||||
# 逻辑未删除值
|
||||
logic-not-delete-value: 0
|
||||
# mapper xml文件位置
|
||||
mapper-locations: classpath*:/mapper/**/*.xml
|
||||
# 实体类包路径
|
||||
type-aliases-package: com.kurihada.auth.entity
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
com.kurihada.auth: debug
|
||||
org.springframework.security: debug
|
||||
com.baomidou.mybatisplus: debug
|
||||
@@ -0,0 +1,259 @@
|
||||
-- ========================================
|
||||
-- 认证系统数据库初始化脚本
|
||||
-- 版本: 1.0
|
||||
-- 说明: 包含所有表的创建和初始数据
|
||||
-- ========================================
|
||||
|
||||
-- ========================================
|
||||
-- 1. 租户表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `tenants` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '租户ID',
|
||||
`code` VARCHAR(50) NOT NULL COMMENT '租户代码(唯一标识)',
|
||||
`name` VARCHAR(100) NOT NULL COMMENT '租户名称',
|
||||
`contact_name` VARCHAR(50) COMMENT '联系人',
|
||||
`contact_phone` VARCHAR(20) COMMENT '联系电话',
|
||||
`contact_email` VARCHAR(100) COMMENT '联系邮箱',
|
||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
|
||||
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)',
|
||||
`expire_time` DATETIME COMMENT '过期时间',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_code` (`code`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_deleted` (`deleted`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户表';
|
||||
|
||||
-- ========================================
|
||||
-- 2. 用户表(整合了账户锁定和邮箱验证功能)
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
|
||||
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
|
||||
`password` VARCHAR(255) NOT NULL COMMENT '密码(加密后)',
|
||||
`tenant_id` BIGINT COMMENT '租户ID',
|
||||
`real_name` VARCHAR(50) COMMENT '真实姓名',
|
||||
`email` VARCHAR(100) COMMENT '邮箱',
|
||||
`phone` VARCHAR(20) COMMENT '手机号',
|
||||
`gender` TINYINT COMMENT '性别(0:女,1:男,2:未知)',
|
||||
`avatar` VARCHAR(255) COMMENT '头像URL',
|
||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
|
||||
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)',
|
||||
`last_login_time` DATETIME COMMENT '最后登录时间',
|
||||
-- 账户锁定相关字段
|
||||
`login_failed_count` INT DEFAULT 0 COMMENT '登录失败次数',
|
||||
`account_locked_at` DATETIME NULL COMMENT '账户锁定时间',
|
||||
`account_unlock_at` DATETIME NULL COMMENT '账户解锁时间',
|
||||
-- 邮箱验证相关字段
|
||||
`email_verified` TINYINT(1) DEFAULT 0 COMMENT '邮箱是否已验证(0:未验证,1:已验证)',
|
||||
`email_verified_at` DATETIME DEFAULT NULL COMMENT '邮箱验证时间',
|
||||
-- 时间戳字段
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_username` (`username`),
|
||||
UNIQUE KEY `uk_email` (`email`),
|
||||
KEY `idx_tenant_id` (`tenant_id`),
|
||||
KEY `idx_status_deleted` (`status`, `deleted`),
|
||||
KEY `idx_phone` (`phone`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_last_login_time` (`last_login_time`),
|
||||
KEY `idx_account_locked_at` (`account_locked_at`),
|
||||
KEY `idx_account_unlock_at` (`account_unlock_at`),
|
||||
KEY `idx_email_verified` (`email_verified`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
||||
|
||||
-- ========================================
|
||||
-- 3. 角色表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `roles` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '角色ID',
|
||||
`name` VARCHAR(50) NOT NULL COMMENT '角色名称',
|
||||
`code` VARCHAR(50) NOT NULL COMMENT '角色代码',
|
||||
`tenant_id` BIGINT COMMENT '租户ID',
|
||||
`description` VARCHAR(255) COMMENT '角色描述',
|
||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_code_tenant` (`code`, `tenant_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
|
||||
|
||||
-- ========================================
|
||||
-- 4. 权限表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `permissions` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '权限ID',
|
||||
`name` VARCHAR(50) NOT NULL COMMENT '权限名称',
|
||||
`code` VARCHAR(100) NOT NULL COMMENT '权限代码',
|
||||
`tenant_id` BIGINT COMMENT '租户ID(null表示公共权限)',
|
||||
`description` VARCHAR(255) COMMENT '权限描述',
|
||||
`type` VARCHAR(20) COMMENT '权限类型(menu:菜单,button:按钮,api:接口)',
|
||||
`resource` VARCHAR(255) COMMENT '资源路径(URL或方法)',
|
||||
`parent_id` BIGINT COMMENT '父权限ID',
|
||||
`sort` INT DEFAULT 0 COMMENT '排序',
|
||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_code_tenant` (`code`, `tenant_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`),
|
||||
KEY `idx_parent_id` (`parent_id`),
|
||||
KEY `idx_type` (`type`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_sort` (`sort`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';
|
||||
|
||||
-- ========================================
|
||||
-- 5. 用户角色关联表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `user_roles` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` BIGINT NOT NULL COMMENT '用户ID',
|
||||
`role_id` BIGINT NOT NULL COMMENT '角色ID',
|
||||
`tenant_id` BIGINT COMMENT '租户ID',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_role_tenant` (`user_id`, `role_id`, `tenant_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_role_id` (`role_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
|
||||
|
||||
-- ========================================
|
||||
-- 6. 角色权限关联表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `role_permissions` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`role_id` BIGINT NOT NULL COMMENT '角色ID',
|
||||
`permission_id` BIGINT NOT NULL COMMENT '权限ID',
|
||||
`tenant_id` BIGINT COMMENT '租户ID',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_role_permission_tenant` (`role_id`, `permission_id`, `tenant_id`),
|
||||
KEY `idx_role_id` (`role_id`),
|
||||
KEY `idx_permission_id` (`permission_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';
|
||||
|
||||
-- ========================================
|
||||
-- 7. Refresh Token 表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `refresh_tokens` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` BIGINT NOT NULL COMMENT '用户ID',
|
||||
`token` VARCHAR(100) NOT NULL COMMENT 'Refresh Token',
|
||||
`tenant_id` BIGINT COMMENT '租户ID',
|
||||
`expire_time` DATETIME NOT NULL COMMENT '过期时间',
|
||||
`used` TINYINT NOT NULL DEFAULT 0 COMMENT '是否已使用(0:未使用,1:已使用)',
|
||||
`deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_token` (`token`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`),
|
||||
KEY `idx_expire_time` (`expire_time`),
|
||||
KEY `idx_used` (`used`),
|
||||
KEY `idx_deleted` (`deleted`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Refresh Token表';
|
||||
|
||||
-- ========================================
|
||||
-- 8. 审计日志表
|
||||
-- ========================================
|
||||
CREATE TABLE IF NOT EXISTS `audit_log` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`action_type` VARCHAR(50) NOT NULL COMMENT '操作类型(LOGIN, LOGOUT, CREATE_USER, UPDATE_USER, DELETE_USER, ASSIGN_ROLE, REMOVE_ROLE, etc.)',
|
||||
`user_id` BIGINT COMMENT '操作用户ID',
|
||||
`username` VARCHAR(50) COMMENT '操作用户名',
|
||||
`tenant_id` BIGINT NOT NULL COMMENT '租户ID',
|
||||
`resource_type` VARCHAR(50) COMMENT '资源类型(USER, ROLE, PERMISSION)',
|
||||
`resource_id` VARCHAR(100) COMMENT '资源ID',
|
||||
`details` TEXT COMMENT '操作详情',
|
||||
`result` VARCHAR(20) NOT NULL COMMENT '操作结果(SUCCESS/FAILURE)',
|
||||
`error_message` TEXT COMMENT '错误信息(如果失败)',
|
||||
`ip_address` VARCHAR(50) COMMENT '请求IP地址',
|
||||
`user_agent` VARCHAR(500) COMMENT 'User Agent',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `idx_user_id` (`user_id`),
|
||||
INDEX `idx_username` (`username`),
|
||||
INDEX `idx_tenant_id` (`tenant_id`),
|
||||
INDEX `idx_action_type` (`action_type`),
|
||||
INDEX `idx_result` (`result`),
|
||||
INDEX `idx_create_time` (`create_time`),
|
||||
INDEX `idx_composite_user_time` (`user_id`, `create_time`),
|
||||
INDEX `idx_composite_action_result` (`action_type`, `result`, `create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审计日志表 - 记录系统中的所有重要操作';
|
||||
|
||||
-- ========================================
|
||||
-- 初始化数据
|
||||
-- ========================================
|
||||
|
||||
-- 插入租户数据
|
||||
INSERT INTO `tenants` (`code`, `name`, `contact_name`, `status`)
|
||||
VALUES ('default', '默认租户', '系统管理员', 1);
|
||||
|
||||
INSERT INTO `tenants` (`code`, `name`, `contact_name`, `contact_phone`, `contact_email`, `status`)
|
||||
VALUES
|
||||
('company_a', 'A公司', '张三', '13800138000', 'zhangsan@companya.com', 1),
|
||||
('company_b', 'B公司', '李四', '13900139000', 'lisi@companyb.com', 1);
|
||||
|
||||
-- 插入用户数据
|
||||
-- 密码: admin123 (BCrypt加密)
|
||||
INSERT INTO `users` (`username`, `password`, `tenant_id`, `real_name`, `email`, `status`)
|
||||
VALUES
|
||||
('admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', 1, '系统管理员', 'admin@example.com', 1),
|
||||
('user', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', 1, '普通用户', 'user@example.com', 1);
|
||||
|
||||
-- 插入角色数据
|
||||
INSERT INTO `roles` (`name`, `code`, `tenant_id`, `description`, `status`)
|
||||
VALUES
|
||||
('超级管理员', 'ADMIN', 1, '拥有所有权限', 1),
|
||||
('普通用户', 'USER', 1, '基础用户权限', 1);
|
||||
|
||||
-- 插入权限数据(公共权限,tenant_id 为 NULL)
|
||||
INSERT INTO `permissions` (`name`, `code`, `tenant_id`, `description`, `type`, `resource`, `parent_id`, `sort`, `status`)
|
||||
VALUES
|
||||
-- 系统管理
|
||||
('系统管理', 'system:manage', NULL, '系统管理模块', 'menu', '/system', NULL, 1, 1),
|
||||
|
||||
-- 用户管理
|
||||
('用户管理', 'user:manage', NULL, '用户管理模块', 'menu', '/system/user', 1, 1, 1),
|
||||
('用户查看', 'user:read', NULL, '查看用户信息', 'api', 'GET:/api/users/**', 2, 1, 1),
|
||||
('用户新增', 'user:create', NULL, '新增用户', 'api', 'POST:/api/users', 2, 2, 1),
|
||||
('用户修改', 'user:update', NULL, '修改用户信息', 'api', 'PUT:/api/users/**', 2, 3, 1),
|
||||
('用户删除', 'user:delete', NULL, '删除用户', 'api', 'DELETE:/api/users/**', 2, 4, 1),
|
||||
|
||||
-- 角色管理
|
||||
('角色管理', 'role:manage', NULL, '角色管理模块', 'menu', '/system/role', 1, 2, 1),
|
||||
('角色查看', 'role:read', NULL, '查看角色信息', 'api', 'GET:/api/roles/**', 7, 1, 1),
|
||||
('角色新增', 'role:create', NULL, '新增角色', 'api', 'POST:/api/roles', 7, 2, 1),
|
||||
('角色修改', 'role:update', NULL, '修改角色信息', 'api', 'PUT:/api/roles/**', 7, 3, 1),
|
||||
('角色删除', 'role:delete', NULL, '删除角色', 'api', 'DELETE:/api/roles/**', 7, 4, 1),
|
||||
|
||||
-- 权限管理
|
||||
('权限管理', 'permission:manage', NULL, '权限管理模块', 'menu', '/system/permission', 1, 3, 1),
|
||||
('权限查看', 'permission:read', NULL, '查看权限信息', 'api', 'GET:/api/permissions/**', 12, 1, 1),
|
||||
('权限新增', 'permission:create', NULL, '新增权限', 'api', 'POST:/api/permissions', 12, 2, 1),
|
||||
('权限修改', 'permission:update', NULL, '修改权限信息', 'api', 'PUT:/api/permissions/**', 12, 3, 1),
|
||||
('权限删除', 'permission:delete', NULL, '删除权限', 'api', 'DELETE:/api/permissions/**', 12, 4, 1);
|
||||
|
||||
-- 插入用户角色关联数据
|
||||
INSERT INTO `user_roles` (`user_id`, `role_id`, `tenant_id`)
|
||||
VALUES
|
||||
(1, 1, 1), -- admin 用户 -> 超级管理员角色
|
||||
(2, 2, 1); -- user 用户 -> 普通用户角色
|
||||
|
||||
-- 插入角色权限关联数据
|
||||
-- 为超级管理员角色分配所有权限
|
||||
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `tenant_id`)
|
||||
SELECT 1, id, 1 FROM `permissions` WHERE `status` = 1;
|
||||
|
||||
-- 为普通用户角色分配查看权限
|
||||
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `tenant_id`)
|
||||
SELECT 2, id, 1 FROM `permissions` WHERE `code` IN ('user:read', 'role:read', 'permission:read');
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.kurihada.auth.mapper.UserMapper">
|
||||
|
||||
<!-- 结果映射:用户及其角色权限 -->
|
||||
<resultMap id="UserWithRolesAndPermissionsMap" type="com.kurihada.auth.entity.User">
|
||||
<id column="user_id" property="id"/>
|
||||
<result column="username" property="username"/>
|
||||
<result column="password" property="password"/>
|
||||
<result column="tenant_id" property="tenantId"/>
|
||||
<result column="real_name" property="realName"/>
|
||||
<result column="email" property="email"/>
|
||||
<result column="phone" property="phone"/>
|
||||
<result column="gender" property="gender"/>
|
||||
<result column="avatar" property="avatar"/>
|
||||
<result column="status" property="status"/>
|
||||
<result column="deleted" property="deleted"/>
|
||||
<result column="email_verified" property="emailVerified"/>
|
||||
<result column="email_verified_at" property="emailVerifiedAt"/>
|
||||
<result column="login_failed_count" property="loginFailedCount"/>
|
||||
<result column="account_locked_at" property="accountLockedAt"/>
|
||||
<result column="account_unlock_at" property="accountUnlockAt"/>
|
||||
<result column="last_login_time" property="lastLoginTime"/>
|
||||
<result column="create_time" property="createTime"/>
|
||||
<result column="update_time" property="updateTime"/>
|
||||
|
||||
<!-- 角色集合 -->
|
||||
<collection property="roles" ofType="com.kurihada.auth.entity.Role">
|
||||
<id column="role_id" property="id"/>
|
||||
<result column="role_name" property="name"/>
|
||||
<result column="role_code" property="code"/>
|
||||
<result column="role_tenant_id" property="tenantId"/>
|
||||
<result column="role_description" property="description"/>
|
||||
<result column="role_status" property="status"/>
|
||||
<result column="role_create_time" property="createTime"/>
|
||||
<result column="role_update_time" property="updateTime"/>
|
||||
|
||||
<!-- 权限集合 -->
|
||||
<collection property="permissions" ofType="com.kurihada.auth.entity.Permission">
|
||||
<id column="permission_id" property="id"/>
|
||||
<result column="permission_name" property="name"/>
|
||||
<result column="permission_code" property="code"/>
|
||||
<result column="permission_tenant_id" property="tenantId"/>
|
||||
<result column="permission_description" property="description"/>
|
||||
<result column="permission_type" property="type"/>
|
||||
<result column="permission_resource" property="resource"/>
|
||||
<result column="permission_parent_id" property="parentId"/>
|
||||
<result column="permission_sort" property="sort"/>
|
||||
<result column="permission_status" property="status"/>
|
||||
<result column="permission_create_time" property="createTime"/>
|
||||
<result column="permission_update_time" property="updateTime"/>
|
||||
</collection>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
<!-- 查询用户及其所有角色和权限(一次查询) -->
|
||||
<select id="selectUserWithRolesAndPermissions" resultMap="UserWithRolesAndPermissionsMap">
|
||||
SELECT
|
||||
u.id AS user_id,
|
||||
u.username,
|
||||
u.password,
|
||||
u.tenant_id,
|
||||
u.real_name,
|
||||
u.email,
|
||||
u.phone,
|
||||
u.gender,
|
||||
u.avatar,
|
||||
u.status,
|
||||
u.deleted,
|
||||
u.email_verified,
|
||||
u.email_verified_at,
|
||||
u.login_failed_count,
|
||||
u.account_locked_at,
|
||||
u.account_unlock_at,
|
||||
u.last_login_time,
|
||||
u.create_time,
|
||||
u.update_time,
|
||||
r.id AS role_id,
|
||||
r.name AS role_name,
|
||||
r.code AS role_code,
|
||||
r.tenant_id AS role_tenant_id,
|
||||
r.description AS role_description,
|
||||
r.status AS role_status,
|
||||
r.create_time AS role_create_time,
|
||||
r.update_time AS role_update_time,
|
||||
p.id AS permission_id,
|
||||
p.name AS permission_name,
|
||||
p.code AS permission_code,
|
||||
p.tenant_id AS permission_tenant_id,
|
||||
p.description AS permission_description,
|
||||
p.type AS permission_type,
|
||||
p.resource AS permission_resource,
|
||||
p.parent_id AS permission_parent_id,
|
||||
p.sort AS permission_sort,
|
||||
p.status AS permission_status,
|
||||
p.create_time AS permission_create_time,
|
||||
p.update_time AS permission_update_time
|
||||
FROM users u
|
||||
LEFT JOIN user_roles ur ON u.id = ur.user_id
|
||||
LEFT JOIN roles r ON ur.role_id = r.id
|
||||
LEFT JOIN role_permissions rp ON r.id = rp.role_id
|
||||
LEFT JOIN permissions p ON rp.permission_id = p.id
|
||||
WHERE u.username = #{username}
|
||||
AND u.deleted = 0
|
||||
</select>
|
||||
|
||||
<!-- 根据用户ID查询用户及其所有角色和权限 -->
|
||||
<select id="selectUserWithRolesAndPermissionsById" resultMap="UserWithRolesAndPermissionsMap">
|
||||
SELECT
|
||||
u.id AS user_id,
|
||||
u.username,
|
||||
u.password,
|
||||
u.tenant_id,
|
||||
u.real_name,
|
||||
u.email,
|
||||
u.phone,
|
||||
u.gender,
|
||||
u.avatar,
|
||||
u.status,
|
||||
u.deleted,
|
||||
u.email_verified,
|
||||
u.email_verified_at,
|
||||
u.login_failed_count,
|
||||
u.account_locked_at,
|
||||
u.account_unlock_at,
|
||||
u.last_login_time,
|
||||
u.create_time,
|
||||
u.update_time,
|
||||
r.id AS role_id,
|
||||
r.name AS role_name,
|
||||
r.code AS role_code,
|
||||
r.tenant_id AS role_tenant_id,
|
||||
r.description AS role_description,
|
||||
r.status AS role_status,
|
||||
r.create_time AS role_create_time,
|
||||
r.update_time AS role_update_time,
|
||||
p.id AS permission_id,
|
||||
p.name AS permission_name,
|
||||
p.code AS permission_code,
|
||||
p.tenant_id AS permission_tenant_id,
|
||||
p.description AS permission_description,
|
||||
p.type AS permission_type,
|
||||
p.resource AS permission_resource,
|
||||
p.parent_id AS permission_parent_id,
|
||||
p.sort AS permission_sort,
|
||||
p.status AS permission_status,
|
||||
p.create_time AS permission_create_time,
|
||||
p.update_time AS permission_update_time
|
||||
FROM users u
|
||||
LEFT JOIN user_roles ur ON u.id = ur.user_id
|
||||
LEFT JOIN roles r ON ur.role_id = r.id
|
||||
LEFT JOIN role_permissions rp ON r.id = rp.role_id
|
||||
LEFT JOIN permissions p ON rp.permission_id = p.id
|
||||
WHERE u.id = #{userId}
|
||||
AND u.deleted = 0
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,166 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>邮箱验证</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 40px auto;
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #ffffff;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.content {
|
||||
padding: 40px 30px;
|
||||
}
|
||||
.greeting {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20px;
|
||||
color: #2d3748;
|
||||
}
|
||||
.message {
|
||||
font-size: 15px;
|
||||
color: #4a5568;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.button-container {
|
||||
text-align: center;
|
||||
margin: 35px 0;
|
||||
}
|
||||
.verify-button {
|
||||
display: inline-block;
|
||||
padding: 14px 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
.verify-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
.alternative {
|
||||
background: #f7fafc;
|
||||
border-left: 4px solid #667eea;
|
||||
padding: 20px;
|
||||
margin: 25px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.alternative p {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
color: #4a5568;
|
||||
}
|
||||
.link {
|
||||
word-break: break-all;
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
}
|
||||
.warning {
|
||||
background: #fff5f5;
|
||||
border-left: 4px solid #f56565;
|
||||
padding: 15px;
|
||||
margin: 25px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.warning p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #742a2a;
|
||||
}
|
||||
.footer {
|
||||
background: #f7fafc;
|
||||
padding: 25px 30px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
.footer p {
|
||||
margin: 5px 0;
|
||||
font-size: 13px;
|
||||
color: #718096;
|
||||
}
|
||||
.expiry {
|
||||
text-align: center;
|
||||
color: #718096;
|
||||
font-size: 14px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>✉️ 验证您的邮箱</h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="greeting">
|
||||
您好,<span th:text="${username}">用户</span>!
|
||||
</div>
|
||||
|
||||
<div class="message">
|
||||
<p>感谢您注册我们的认证系统!</p>
|
||||
<p>为了确保账户安全并激活您的账号,请点击下方按钮验证您的邮箱地址:</p>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<a th:href="${verificationUrl}" class="verify-button">
|
||||
验证邮箱
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="expiry">
|
||||
⏰ 此链接将在 <strong th:text="${validHours}">24</strong> 小时后过期
|
||||
</div>
|
||||
|
||||
<div class="alternative">
|
||||
<p><strong>如果按钮无法点击,请复制以下链接到浏览器:</strong></p>
|
||||
<a th:href="${verificationUrl}" th:text="${verificationUrl}" class="link">
|
||||
验证链接
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="warning">
|
||||
<p>
|
||||
<strong>⚠️ 安全提示:</strong>
|
||||
如果您没有注册我们的服务,请忽略此邮件。您的账户安全不会受到影响。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>此邮件由系统自动发送,请勿直接回复</p>
|
||||
<p>© 2025 认证系统. 保留所有权利</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>密码重置请求</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.logo {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
h1 {
|
||||
color: #2563eb;
|
||||
font-size: 24px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 12px 30px;
|
||||
background-color: #2563eb;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
.button-container {
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
}
|
||||
.warning {
|
||||
background-color: #fef3c7;
|
||||
border-left: 4px solid #f59e0b;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
.link {
|
||||
word-break: break-all;
|
||||
color: #2563eb;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<h1>🔐 Auth System</h1>
|
||||
</div>
|
||||
|
||||
<h1>密码重置请求</h1>
|
||||
|
||||
<div class="content">
|
||||
<p>您好,<strong th:text="${username}">用户</strong>!</p>
|
||||
|
||||
<p>我们收到了您的密码重置请求。如果这不是您的操作,请忽略此邮件。</p>
|
||||
|
||||
<p>要重置您的密码,请点击下面的按钮:</p>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<a th:href="${resetUrl}" class="button">重置密码</a>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<p>或者复制以下链接到浏览器:</p>
|
||||
<p><a th:href="${resetUrl}" th:text="${resetUrl}" class="link">重置链接</a></p>
|
||||
</div>
|
||||
|
||||
<div class="warning">
|
||||
<p><strong>⏰ 重要提示:</strong></p>
|
||||
<ul>
|
||||
<li>此链接将在 <span th:text="${validMinutes}">60</span> 分钟后失效</li>
|
||||
<li>为了您的账号安全,请不要将此链接分享给他人</li>
|
||||
<li>如果您没有请求重置密码,请忽略此邮件</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>此邮件由系统自动发送,请勿直接回复。</p>
|
||||
<p>© 2025 Auth System. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user