签入版本
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
:::tip 用户管理
|
||||
用户管理是系统的核心模块,属于复杂业务模块。包含用户 CRUD、角色关联、密码加密、行政区划等功能。与简单 CRUD 模块不同,用户管理使用自定义 service 函数。
|
||||
:::
|
||||
|
||||
## 模块结构
|
||||
|
||||
```
|
||||
application/user/
|
||||
├── models.py # 用户模型
|
||||
├── forms.py # 表单验证
|
||||
├── services.py # 业务逻辑层(自定义函数)
|
||||
├── views.py # 视图层
|
||||
└── urls.py # 路由配置
|
||||
|
||||
application/user_role/
|
||||
├── models.py # 用户-角色关联模型
|
||||
├── services.py # 关联业务逻辑
|
||||
└── urls.py # 路由配置
|
||||
```
|
||||
|
||||
## 用户模型
|
||||
|
||||
```python
|
||||
# application/user/models.py
|
||||
from application.models import BaseModel
|
||||
|
||||
class User(BaseModel):
|
||||
"""用户模型类"""
|
||||
class Meta:
|
||||
db_table = 'django_user'
|
||||
|
||||
code = models.CharField(max_length=100, default='', verbose_name='用户编码')
|
||||
realname = models.CharField(max_length=150, verbose_name='用户姓名')
|
||||
gender = models.IntegerField(default=1, verbose_name='性别:1-男 2-女 3-保密')
|
||||
avatar = models.CharField(max_length=255, default='', verbose_name='用户头像')
|
||||
mobile = models.CharField(max_length=30, default='', verbose_name='手机号')
|
||||
email = models.CharField(max_length=30, default='', verbose_name='邮箱')
|
||||
dept_id = models.IntegerField(default=0, verbose_name='部门ID')
|
||||
level_id = models.IntegerField(default=0, verbose_name='职级ID')
|
||||
position_id = models.IntegerField(default=0, verbose_name='岗位ID')
|
||||
province_code = models.CharField(max_length=30, default='', verbose_name='省份编码')
|
||||
city_code = models.CharField(max_length=30, default='', verbose_name='城市编码')
|
||||
district_code = models.CharField(max_length=30, default='', verbose_name='县区编码')
|
||||
street_code = models.CharField(max_length=30, default='', verbose_name='街道编码')
|
||||
city_info = models.CharField(max_length=255, null=True, blank=True, verbose_name='省市区信息')
|
||||
address = models.CharField(max_length=255, default='', verbose_name='详细地址')
|
||||
username = models.CharField(max_length=30, null=True, blank=True, verbose_name='用户名')
|
||||
password = models.CharField(max_length=255, null=True, blank=True, verbose_name='密码')
|
||||
salt = models.CharField(max_length=30, null=True, blank=True, verbose_name='加密盐')
|
||||
intro = models.CharField(max_length=255, null=True, blank=True, verbose_name='个人简介')
|
||||
status = models.IntegerField(default=1, verbose_name='状态:1-正常 2-禁用')
|
||||
sort = models.IntegerField(default=0, verbose_name='排序')
|
||||
note = models.CharField(max_length=255, null=True, blank=True, verbose_name='个人备注')
|
||||
```
|
||||
|
||||
## 密码加密
|
||||
|
||||
使用 bcrypt 双重加盐方案,由 `utils/password.py` 提供:
|
||||
|
||||
```python
|
||||
# utils/password.py
|
||||
import secrets
|
||||
import bcrypt
|
||||
|
||||
BCRYPT_ROUNDS = 12
|
||||
|
||||
def generate_salt(length=10):
|
||||
"""生成随机盐值"""
|
||||
return secrets.token_urlsafe(length)[:length]
|
||||
|
||||
def encrypt_password(password, salt):
|
||||
"""使用 bcrypt 加密密码(外部 salt 双重加盐)"""
|
||||
combined = (password + salt).encode('utf-8')
|
||||
hashed = bcrypt.hashpw(combined, bcrypt.gensalt(rounds=BCRYPT_ROUNDS))
|
||||
return hashed.decode('utf-8')
|
||||
|
||||
def verify_password(password, salt, hashed):
|
||||
"""验证密码是否正确"""
|
||||
combined = (password + salt).encode('utf-8')
|
||||
return bcrypt.checkpw(combined, hashed.encode('utf-8'))
|
||||
```
|
||||
|
||||
:::tip 双重加盐
|
||||
密码加密采用双重加盐:外部 salt(存储在 user 表)+ bcrypt 内部 salt。即使数据库泄露,攻击者也无法通过彩虹表破解密码。工作因子 12,单次加密约 250ms。
|
||||
:::
|
||||
|
||||
## 角色关联
|
||||
|
||||
用户与角色通过 `django_user_role` 关联表实现多对多关系:
|
||||
|
||||
```python
|
||||
# application/user_role/models.py
|
||||
class UserRole(BaseModel):
|
||||
"""用户角色关联模型类"""
|
||||
class Meta:
|
||||
db_table = 'django_user_role'
|
||||
|
||||
user_id = models.IntegerField(default=0, verbose_name='用户ID')
|
||||
role_id = models.IntegerField(default=0, verbose_name='角色ID')
|
||||
```
|
||||
|
||||
## 关联数据富化
|
||||
|
||||
用户列表和详情需要富化部门、职级、岗位、角色等关联数据:
|
||||
|
||||
```python
|
||||
# application/user/services.py
|
||||
def _enrich_user_records(records):
|
||||
"""为用户记录补充关联数据"""
|
||||
dept_map = {d.id: d.name for d in Dept.objects.filter(is_delete=False)}
|
||||
level_map = {l.id: l.name for l in Level.objects.filter(is_delete=False)}
|
||||
position_map = {p.id: p.name for p in Position.objects.filter(is_delete=False)}
|
||||
|
||||
for data in records:
|
||||
data["deptName"] = dept_map.get(data.get("deptId"))
|
||||
data["levelName"] = level_map.get(data.get("levelId"))
|
||||
data["positionName"] = position_map.get(data.get("positionId"))
|
||||
|
||||
return records
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
| 接口 | 方法 | 权限节点 | 说明 |
|
||||
|------|------|---------|------|
|
||||
| `/user/page` | GET | `sys:user:page` | 用户分页列表 |
|
||||
| `/user/detail/<int:user_id>` | GET | `sys:user:detail` | 用户详情 |
|
||||
| `/user/add` | POST | `sys:user:add` | 新增用户 |
|
||||
| `/user/update` | POST | `sys:user:update` | 编辑用户 |
|
||||
| `/user/delete/<int:user_id>` | POST | `sys:user:delete` | 删除用户 |
|
||||
| `/user/status` | POST | `sys:user:status` | 设置状态 |
|
||||
| `/user/resetPwd` | POST | `sys:user:resetPwd` | 重置密码 |
|
||||
|
||||
:::warning 内置超管保护
|
||||
用户 ID 为 1 的内置超管账号禁止通过管理接口修改、删除、禁用、重置密码。这些操作会在 service 层提前拦截并返回失败提示。
|
||||
:::
|
||||
|
||||
## 总结
|
||||
|
||||
用户管理模块具备以下特点:
|
||||
|
||||
```
|
||||
1. 复杂业务:自定义 service 函数,处理关联数据
|
||||
2. 密码安全:bcrypt 双重加盐,工作因子12
|
||||
3. 角色关联:多对多关系,通过 user_role 关联表
|
||||
4. 关联富化:列表/详情补充部门、职级、岗位、角色等展示名称
|
||||
5. 行政区划:省/市/区/街道四级编码
|
||||
6. 超管保护:ID=1 账号禁止修改/删除/禁用/重置密码
|
||||
```
|
||||
Reference in New Issue
Block a user