简介
CASL是一个强大的权限控制库,可以帮助我们实现灵活的RBAC(基于角色的访问控制)系统。本文将介绍如何使用CASL实现用户权限管理。
CASL的核心概念
1. Ability(能力)
javascript
import { AbilityBuilder, Ability } from '@casl/ability'
const ability = new Ability([
{ action: 'read', subject: 'Article' },
{ action: 'update', subject: 'Article', conditions: { authorId: user.id } }
])
2. 定义规则
javascript
const { can, cannot, build } = new AbilityBuilder(Ability)
// 定义管理员权限
can('manage', 'all') // 管理员可以管理所有资源
// 定义普通用户权限
can('read', 'Article') // 可以阅读文章
can('create', 'Comment') // 可以创建评论
cannot('delete', 'Article').because('只有管理员可以删除文章')
实现RBAC权限控制
1. 定义角色和权限映射
typescript
// permissions.ts
export const rolePermissions = {
admin: [
{ action: 'manage', subject: 'all' }
],
editor: [
{ action: 'read', subject: 'Article' },
{ action: 'create', subject: 'Article' },
{ action: 'update', subject: 'Article', conditions: { authorId: '${user.id}' } }
],
user: [
{ action: 'read', subject: 'Article' },
{ action: 'create', subject: 'Comment' }
]
}
2. 创建Ability实例
typescript
// ability.ts
import { Ability } from '@casl/ability'
export function createAbility(user) {
const permissions = rolePermissions[user.role]
return new Ability(permissions.map(permission => ({
...permission,
conditions: permission.conditions ?
JSON.parse(interpolate(permission.conditions, { user })) :
undefined
})))
}
3. 在Vue中使用
vue
<!-- ArticleList.vue -->
<template>
<div v-for="article in articles" :key="article.id">
<h2>{{ article.title }}</h2>
<div class="actions">
<button v-if="$can('update', article)">编辑</button>
<button v-if="$can('delete', article)">删除</button>
</div>
</div>
</template>
<script>
export default {
methods: {
async deleteArticle(article) {
if (this.$can('delete', article)) {
await this.performDelete(article)
}
}
}
}
</script>
4. 在API请求中使用
typescript
// article.service.ts
export class ArticleService {
async updateArticle(id: string, data: any, ability: Ability) {
const article = await this.findById(id)
if (ability.can('update', article)) {
return await this.articleRepo.update(id, data)
}
throw new Error('没有权限执行此操作')
}
}
最佳实践
-
权限粒度控制
- 合理划分权限粒度
- 避免过于复杂的权限规则
-
动态权限
typescript
// 支持动态更新权限
ability.update([
{ action: 'read', subject: 'Article' },
{ action: 'update', subject: 'Article', conditions: { status: 'draft' } }
])
- 权限缓存
typescript
// 使用localStorage缓存权限规则
const cacheKey = `permissions_${user.id}`
const cachedRules = localStorage.getItem(cacheKey)
if (cachedRules) {
ability.update(JSON.parse(cachedRules))
} else {
const rules = await fetchUserPermissions(user.id)
localStorage.setItem(cacheKey, JSON.stringify(rules))
ability.update(rules)
}
总结
CASL提供了一个灵活且强大的权限控制解决方案:
- 支持细粒度的权限控制
- 可以轻松实现RBAC模型
- 与前端框架良好集成
- 支持动态权限更新
- 提供直观的API
通过合理使用CASL,我们可以构建出一个安全、可维护的权限管理系统。