在之前的实战示例中,我们构建并优化了商品管理系统,实现了一系列功能。然而,在实际应用场景中,系统的安全性和权限管理至关重要。本示例将重点介绍如何在现有系统中集成权限管理功能,确保不同用户角色具有合适的操作权限,同时增强系统的整体安全性。
一、权限管理设计
-
角色与权限定义
- 确定系统中的角色,例如管理员、普通用户等。管理员具有对商品的完全管理权限,包括添加、编辑、删除、查看所有商品等操作;普通用户可能仅具有查看商品信息的权限。
- 为每个角色分配具体的权限,这些权限将与系统中的操作(如路由访问、API调用等)相对应。
-
数据库设计
- 在数据库中创建
roles
表,用于存储角色信息,包括role_id
(角色ID)、role_name
(角色名称)等字段。
- 在数据库中创建
sql
CREATE TABLE roles (
role_id INT AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(50) NOT NULL
);
- 创建`role_permissions`表,用于关联角色和权限,包含`role_id`、`permission_name`(权限名称,如`add_product`、`edit_product`等)等字段。
sql
CREATE TABLE role_permissions (
role_id INT,
permission_name VARCHAR(50) NOT NULL,
FOREIGN KEY (role_id) REFERENCES roles(role_id)
);
- 在`users`表中添加`role_id`字段,用于关联用户和其所属角色。
sql
ALTER TABLE users ADD COLUMN role_id INT;
ALTER TABLE users ADD FOREIGN KEY (role_id) REFERENCES roles(role_id);
二、后端权限验证实现
- 中间件创建
在后端项目中创建一个权限验证中间件,用于拦截请求并验证用户的权限。例如,创建一个名为authorization.middleware.js
的文件:
javascript
const jwt = require('jsonwebtoken');
const RolePermissions = require('../models/role_permissions.model');
module.exports = async (req, res, next) => {
try {
// 从请求头中获取令牌(假设前端在登录后将令牌存储在请求头中)
const token = req.headers.authorization.split(' ')[1];
const decodedToken = jwt.verify(token, 'your_secret_key');
const userId = decodedToken.userId;
// 根据用户ID获取用户角色(假设在用户模型中有相关方法获取角色信息)
const userRole = await getUserRole(userId);
// 根据用户角色获取其拥有的权限
const permissions = await RolePermissions.findAll({ where: { role_id: userRole.role_id } });
const permissionNames = permissions.map(permission => permission.permission_name);
// 检查当前请求的操作是否在用户权限范围内(假设在路由定义时有相应的权限标识)
const requiredPermission = req.route.path.split('/')[2]; // 根据实际路由结构获取权限标识
if (!permissionNames.includes(requiredPermission)) {
return res.status(403).json({ message: '没有权限执行此操作' });
}
next();
} catch (error) {
console.error('权限验证失败:', error);
res.status(401).json({ message: '未授权的访问' });
}
};
这个中间件首先验证用户提供的令牌,获取用户ID,然后查询用户的角色和相应的权限。最后,检查当前请求的操作是否在用户权限范围内,如果不在则返回相应的错误状态码。
- 路由保护
在定义商品管理相关的路由时,应用权限验证中间件。例如,在product.routes.js
文件中:
javascript
const authorizationMiddleware = require('../middleware/authorization.middleware');
router.post('/products', authorizationMiddleware, async (req, res) => {
// 只有具有相应权限的用户才能添加商品
// 其他路由处理逻辑
});
router.put('/products/:id', authorizationMiddleware, async (req, res) => {
// 编辑商品路由
});
router.delete('/products/:id', authorizationMiddleware, async (req, res) => {
// 删除商品路由
});
三、前端权限控制
- 用户角色获取与存储
在用户登录成功后,后端返回用户信息中包含角色信息。前端将用户角色存储在Vuex或本地存储中,以便在后续操作中进行权限判断。例如,在Login.vue
组件的loginUser
方法中,成功登录后:
typescript
// 假设登录成功后后端返回的数据格式为 { token: string, user: { role: string } }
const response = await axios.post('/api/login', userData);
const userRole = response.data.user.role;
// 将用户角色存储到Vuex或本地存储中
this.$store.commit('setUserRole', userRole); // 如果使用Vuex
localStorage.setItem('userRole', userRole); // 如果使用本地存储
- 组件级权限控制
在Vue组件中,根据用户角色来控制组件的显示或隐藏,以及操作按钮的可用性。例如,在ProductManagement.vue
组件中:
html
<template>
<div class="product-management-container">
<h2>商品管理</h2>
<!-- 只有管理员才能看到添加商品表单 -->
<form v-if="userRole === 'admin'" @submit.prevent="addProduct">
<!-- 表单内容 -->
</form>
<ul>
<li v-for="product in products" :key="product.id">
<!-- 商品信息展示 -->
<button v-if="userRole === 'admin'" @click="editProduct(product)">编辑</button>
<button v-if="userRole === 'admin'" @click="deleteProduct(product.id)">删除</button>
</li>
</ul>
</div>
</template>
<script lang="ts">
import { mapState } from 'vuex'; // 如果使用Vuex
export default {
name: 'ProductManagement',
computed: {
...mapState(['userRole']) // 如果使用Vuex,从Vuex中获取用户角色
// 如果使用本地存储,可以直接从localStorage中获取
userRole() {
return localStorage.getItem('userRole');
}
},
// 其他组件逻辑
};
</script>
四、系统安全增强
- 输入数据验证与过滤
在前端和后端对用户输入的数据进行严格的验证和过滤,防止SQL注入、XSS攻击等安全漏洞。例如,在后端使用express-validator
库对请求数据进行验证,在前端使用HTML模板引擎的转义功能对显示的数据进行转义。 - 令牌安全
确保令牌的生成、存储和传输安全。使用强密码对令牌进行签名,设置合理的令牌过期时间,并且在传输过程中使用HTTPS协议,防止令牌被窃取或篡改。 - 密码安全
对用户密码进行哈希处理时,使用强哈希算法(如bcrypt)并定期更新哈希算法的强度。同时,鼓励用户使用强密码,并提供密码强度提示功能。
通过以上权限管理和系统安全增强措施,我们的商品管理系统在安全性方面得到了显著提升,确保不同用户角色只能执行其被授权的操作,同时有效防范了各种常见的安全威胁。在实际项目中,还可以根据具体需求进一步细化权限管理策略,加强安全监控和审计等功能。希望本示例对你在构建安全可靠的Vue + TS + MySQL应用程序方面有所帮助,如有任何疑问或建议,欢迎在评论区留言。