Мысли и практика контроля привилегий в системе фонового управления Vue

Vue.js

предисловие

Недавно при разработке системы управления я столкнулся с требованием, которое будет иметь любая система управления - контроль полномочий.Я также сталкивался с этим требованием ранее, но различные проблемы, вызванные несовершенной архитектурой, делают последующее сопровождение очень хлопотным.На этот раз решение это решить После всех предыдущих проблем, я сейчас сделаю запись.Конечно, могут быть ямы на более позднем этапе этой архитектуры, но это требует пошаговой попытки найти и решить проблему.

требования к контролю доступа

Так как это одностраничное приложение, управление маршрутизацией передается внешнему интерфейсу, и особенно важно защитить некоторую информацию, для просмотра которой требуются определенные разрешения.

Для управления разрешениями требования примерно следующие:

  1. Для ограничения больших модулей, таких как модули, которые необходимо перепрыгнуть путем маршрутизации, в настоящее время требуется перехват маршрутизации.
  2. Для ограничений мелких функций, таких как кнопка, если нет специального разрешения, то кнопка отображаться не будет

Размышления на уровне безопасности

Перед тем, как взять на себя систему управления, внешний интерфейс представляет собой список разрешений для достижения долговременной памяти, хранящейся в хранилище, такая реализация очень нежелательна, поскольку хакер может вручную изменить хранимую информацию, чтобы добиться доступа к определенным привилегиям даже в системе. не выполняет перехват маршрутизации, если вы знаете модуль маршрутизации, вы можете перейти непосредственно к конкретному модулю, введя информацию о маршрутизации напрямую. Из-за привилегий некоторых модулей изменения прав администратора не могут вступить в силу немедленно, поэтому для таких ситуаций подумайте и попрактикуйтесь в следующем.

Разрешения вступают в силу сразу после изменения администратором

Для этого требования мой подход заключается в том, чтобы хранить информацию о разрешениях в списке разрешений после получения списка разрешений.vuex store, и используйте функцию получения, чтобы определить, можно ли использовать разрешение, чтобы после обновления данных разрешения функциональная точка ограничения разрешений переднего плана была автоматически изменена, чтобы получить разрешение в реальном времени, что примерно реализовано следующим образом:

// vuex state.js
export default {
    userPrivileges: {
        admin: [],
        purchaser: []
    }, // 用户权限信息
}

// vuex getters.js
export default {
    canIUse: state => (role, id) => state.userPrivileges[role].includes(id)
}

// 页面具体小功能,通过 mapGetters 引入 canIUse 函数
<span v-if="canIUse('admin', 9)">{{scope.row.allocation_subtotal}}</span>

Таким образом, данные хранятся в памяти, поэтому информацию о разрешениях нельзя легко изменить, и оценка разрешений также очень проста.Для определения необходимо только передать идентификатор разрешения функциональной точки в конкретной функциональной точке. можно ли использовать разрешение.

Но хранение данных в памяти также столкнется с проблемой, как насчет обновления страницы? Далее стоит объяснить эту ситуацию.

Обновить страницу также могут быть разрешения

Для перехвата разрешений больших модулей они должны быть перехвачены с помощью перехватчиков маршрутизации (эта реализация была объяснена во многих статьях и не будет здесь подробно объясняться), но предпосылка перехвата с помощью перехватчиков маршрутизации заключается в том, что информация о разрешениях должна существовать. заранее, авансом.

Это происходит при обновлении страницы. При обновлении страницы сначала выполняется хук маршрутизации, а затем выполняется хук жизненного цикла компонента для запроса списка разрешений. В это время информация о разрешениях не существует, поэтому, если страница переходит на страницу входа, опыта недостаточно.

Поэтому мой подход заключается в создании промежуточной страницы. Если проверка разрешения не удалась, перейдите на промежуточную страницу и запросите разрешение на промежуточной странице. После запроса разрешения я буду судить, можно ли его перепрыгнуть. В этом случае опыт страницы будет обновлен лучше. Примерный код выглядит следующим образом:

// vuex actions.js
// 通过返回一个promise,使得store更新与后续代码变为“同步”执行
export default {
    getUserPrivileges({ commit }) {
        return fetch.get({
            url: '/currentstaff'
        }).then(data => {
            commit('SET_USER_PRIVILEGES_INFO', data.data)
            return data.data
        }).catch(e => {

        })
    }
}

// router.js
// 需要验证权限的路由
{
    path: 'suppliers',
    component: Suppliers,
    meta: {
        role: 'admin',
        privilegeId: 5
    }
}

function isCanUseThisModule(to, from) {
    return to.matched.every(record => {
        // 利用路由meta存储相应权限信息
        if (record.meta.role) {
            return store.getters.canIUse(record.meta.role, record.meta.privilegeId)
        } else {
            return true // 如果不需要权限,直接返回true
        }
    })
}

router.beforeEach((to, from, next) => {
    if (isCanUseThisModule(to, from)) {
        next() // 权限验证通过,跳转下一路由
    } else {
        next({
            path: '/main/privilegeValidator' // 权限验证不通过时的中间页
        })
    }
})

// 权限校验中间页代码示例
created() {
    this.$store.dispatch('getUserPrivileges').then(data => {
        for (let i = 0; i < data.admin_permissions.length; i++) {
            if (this.canIUse('admin', data.admin_permissions[i])) {
                this.$router.push({
                    path: this.routerList.find(value => value.privilegeId === data.admin_permissions[i]).linkHref
                })
                return
            }
        }
        this.$router.push('/login') // 如果没有任何权限,则跳转登陆页面
    })
}

После входа в систему пользователь также может перейти на эту промежуточную страницу разрешения, а затем перейти к соответствующему модулю после оценки разрешения.

конец

Общий процесс реализации такой, надеюсь будет всем полезен, а если есть темные ямки, прошу указать.