laravel - 使用 vuejs 和 laravel 的权限和角色
问题描述
这是我使用 CASL 的当前设置。目前它似乎没有读取我要导入到 ability.js 文件中的规则数组。如果您也想查看,我还将功能插件导入到 main.js 文件中
这是ability.js文件
import { Ability } from '@casl/ability'
export const ability = new Ability()
export const abilityPlugin = (store) => {
ability.update(store.state.rules)
return store.subscribe((mutation) => {
switch (mutation.type) {
case 'createSession':
ability.update(mutation.payload.rules)
break
case 'destroySession':
ability.update([{ actions: 'read', subject: 'all' }])
break
}
})
}
这是调用规则列表的商店
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import storage from './utils/storage'
import { abilityPlugin, ability as appAbility } from './utils/ability'
export const ability = appAbility
Vue.use(Vuex)
axios.defaults.baseURL = 'http://todo-laravel.test/api'
export default new Vuex.Store({
plugins: [
storage({
storedKeys: ['rules'],
destroyOn: ['destroySession']
}),
abilityPlugin
],
state: {
rules: '',
token: localStorage.getItem('access_token') || null,
},
mutations: {
createSession(state, role) {
state.rules = role[0]
},
destroySession(state) {
state.rules = ''
},
retrieveToken(state, token) {
state.token = token
},
destroyToken(state) {
state.token = null
},
},
actions: {
destroyToken(context) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token
if (context.getters.loggedIn) {
return new Promise((resolve, reject) => {
axios.post('/logout')
.then(response => {
localStorage.removeItem('access_token')
context.commit('destroyToken')
context.commit('destroySession')
resolve(response)
})
.catch(error => {
localStorage.removeItem('access_token')
context.commit('destroyToken')
reject(error)
})
})
}
},
retrieveToken({ commit, dispatch }, credentials) {
return new Promise((resolve, reject) => {
axios.post('/login', {
username: credentials.username,
password: credentials.password,
})
.then(response => {
const token = response.data.access_token
localStorage.setItem('access_token', token)
commit('retrieveToken', token)
dispatch('retrieveRules')
resolve(response)
})
.catch(error => {
console.log(error)
reject(error)
})
})
},
retrieveRules(context) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token
return new Promise((resolve, reject) => {
axios.get('/rules')
.then(response => {
console.log(response.data)
context.commit('createSession', response.data)
resolve(response)
})
.catch(error => {
console.log(error.response.data)
reject(error)
})
})
},
这是保存在存储中的规则数组
[{id: 1, role_id: 3, action: "Manage", subject: "All"}]
解决方案
您需要定义可以在该主题上执行的 subjets 和操作(例如,用户可以阅读帖子翻译为 -> 主题:“帖子”,操作:“阅读”)。当您这样做时,您可以在 API 端为经过身份验证的用户创建一个路由(或将其作为身份验证响应的一部分返回),该路由返回用户特定的操作。例如:
如果用户是管理员,他可以做任何事情,所以响应应该是:
{
"rules": [
{ "action": "manage", "subject": "all" }
]
}
如果用户是团队成员,那么他有一些受限的权限(假设他只能读取设置):
{
"rules": [
{ "action": "read", "subject": "Settings" }
]
}
在用户界面方面:
如果你不使用 Vuex:
// main.js
import { abilitiesPlugin } from '@casl/vue'
import Vue from 'vue'
Vue.use(abilitiesPlugin);
// inside LoginComponent
{
methods: {
login() {
return this.http.post(...)
.then(respose => this.$ability.update(response.data.rules)
}
}
}
如果你使用 Vuex:
// main.js
import { abilitiesPlugin } from '@casl/vue'
import Vue from 'vue'
import ability from './services/ability';
Vue.use(abilitiesPlugin, ability);
// services/ability.js
import { Ability } from '@casl/ability';
export default new Ability()
// store.js
import ....
import ability from './services/ability'
const updateAbilities = (store) => {
ability.update(store.state.rules) // take rules from your state structure
return store.subscribe((mutation) => {
switch (mutation.type) {
case 'login':
ability.update(mutation.payload.rules)
break
case 'logout':
ability.update([{ actions: 'read', subject: 'all' }]) // read only mode
// or `ability.update([])` to remove all permissions
break
}
})
}
export default new Vuex.Store({
plugins: [
updateAbilities
],
// ... your store declaration
})
您可以查看https://github.com/stalniy/casl-vue-api-example这是 Vue、CASL 和 Rails 集成的示例,以查看一些详细信息
更新:
稍后在所有组件中,只需使用$can
函数或<can>
组件来检查权限。查看CASL Vue 文档了解详细信息
推荐阅读
- api - 为什么 Telethon 发送文件这么慢?
- python - 如何将 txt 文件导入到 ipickle 文件中?
- scrapy - 无法使用 scrapy 抓取页面网页的部分内容
- javascript - VueJs 不显示从 axios 承诺中获取的图像,然后将图像 url 放入 src
- java - 用数字而不是索引编辑arraylist
- java - 实现缓存框架(ehcache)以在服务器启动期间缓存 Lookupcode 和 Location 下拉值
- angular - 如何创建自定义原理图以创建新的角度项目和一些文件
- android - 如何在没有 READ_CALL_LOG 权限的情况下在 Android 9 中获取来电和去电号码?
- mql4 - 简单移动平均线交叉策略不起作用
- sql-server - 一年中几周的填充表跳过了 2021 年的第一周