首页 > 解决方案 > react-admin 授权权限

问题描述

我尝试使用 react-admin 和节点服务器使授权和权限可用:https ://github.com/hagopj13/node-express-mongoose-boilerplate

对于 react-admin 有一个代码示例:https ://marmelab.com/react-admin/Authorization.html#configuring-the-auth-provider

// in src/authProvider.js
import decodeJwt from 'jwt-decode';

export default {
    login: ({ username, password }) => {
        const request = new Request('https://example.com/authenticate', {
            method: 'POST',
            body: JSON.stringify({ username, password }),
            headers: new Headers({ 'Content-Type': 'application/json' }),
        });
        return fetch(request)
            .then(response => {
                if (response.status < 200 || response.status >= 300) {
                    throw new Error(response.statusText);
                }
                return response.json();
            })
            .then(({ token }) => {
                const decodedToken = decodeJwt(token);
                localStorage.setItem('token', token);
                localStorage.setItem('permissions', decodedToken.permissions);
            });
    },
    logout: () => {
        localStorage.removeItem('token');
        localStorage.removeItem('permissions');
        return Promise.resolve();
    },
    checkError: error => {
        // ...
    },
    checkAuth: () => {
        return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
    },
    getPermissions: () => {
        const role = localStorage.getItem('permissions');
        return role ? Promise.resolve(role) : Promise.reject();
    }
};

但我不明白它是如何工作的,登录时服务器返回一个像这样的用户对象:

{user: {id: "5e429d562910776587c567a2", email: "admin@test.com", firstname: "Ad", lastname: "Min",…},…}
tokens: {access: {,…}, refresh: {,…}}
access: {,…}
expires: "2020-03-03T06:45:10.851Z"
token: "eyJhbGciOi..."
refresh: {,…}
expires: "2020-04-02T06:15:10.851Z"
token: "eyJhbGciOi..."
user: {id: "5e429d562910776587c567a2", email: "admin@test.com", firstname: "Ad", lastname: "Min",…}
createdAt: "2020-02-11T12:25:58.760Z"
email: "admin@test.com"
firstname: "Ad"
id: "5e429d562910776587c567a2"
lastname: "Min"
role: "admin"
updatedAt: "2020-02-11T12:25:58.760Z"

已经有token和role了,在服务端,好像有个权限控制:role.js

const roles = ['user', 'admin'];

const roleRights = new Map();
roleRights.set(roles[0], []);
roleRights.set(roles[1], ['getUsers', 'manageUsers']);

module.exports = {
  roles,
  roleRights,
};

和 auth.js

const passport = require('passport');
const httpStatus = require('http-status');
const AppError = require('../utils/AppError');
const { roleRights } = require('../config/roles');

const verifyCallback = (req, resolve, reject, requiredRights) => async (err, user, info) => {
  if (err || info || !user) {
    return reject(new AppError(httpStatus.UNAUTHORIZED, 'Please authenticate'));
  }
  req.user = user;

  if (requiredRights.length) {
    const userRights = roleRights.get(user.role);
    const hasRequiredRights = requiredRights.every(requiredRight => userRights.includes(requiredRight));
    if (!hasRequiredRights && req.params.userId !== user.id) {
      return reject(new AppError(httpStatus.FORBIDDEN, 'Forbidden'));
    }
  }

  resolve();
};

const auth = (...requiredRights) => async (req, res, next) => {
  return new Promise((resolve, reject) => {
    passport.authenticate('jwt', { session: true }, verifyCallback(req, resolve, reject, requiredRights))(req, res, next);
  })
    .then(() => next())
    .catch(err => next(err));
};

module.exports = auth;

但是如何从 react-admin 获得授权和许可?

感谢和问候

卢多

标签: node.jspermissionsauthorizationreact-admin

解决方案


在 react-admin 中有一个 usePermissions() 钩子,它在挂载时调用 authProvider.getPermissions() 方法。此方法返回给您单个字符串值,如 'admin' 或权限字符串数组,如 ['admin','crm'...]。这个字符串取决于你如何设置。在下面的示例中,它存储在 localStorage 中,但在现实生活中需要从 JWT 令牌中提取它或从后端检索它。

  getPermissions: () => {
        const role = localStorage.getItem('permissions');
        return role ? Promise.resolve(role) : Promise.reject();
    }
import { usePermissions } from 'react-admin';
in function
const { permissions } = usePermissions();

return (
 { permissions == 'admin' &&
  <DashboardMenuItem primaryText="Dashboard" onClick={onMenuClick} sidebarIsOpen={open} />
 }
...
);

推荐阅读