跳到主要内容

权限管理

对于移动端场景,鉴权通常由 SSO 或统一登录平台完成,业务开发者无需关注。本文档主要介绍中后台场景中的权限管理。

示例

中后台 Web 应用中,权限管理是经常会涉及的需求之一,通常包含以下几种常见的权限管理类型:

  • 页面权限:当用户访问某个没有权限的页面时跳转到无权限页面
  • 操作权限:页面中的某些按钮或组件针对无权限的用户直接隐藏
  • 接口权限:当用户通过操作调用没有权限的接口时跳转到无权限页面

ice.js 提供 @ice/plugin-auth 插件,帮助用户更简单管理前两种类型的权限。接口权限管理请见数据请求文档。

安装插件

安装插件:

$ npm i @ice/plugin-auth -D

ice.config.mts 中添加插件:

ice.config.mts
import { defineConfig } from '@ice/app';
import auth from '@ice/plugin-auth';

export default defineConfig(() => ({
plugins: [
auth(),
],
}));

初始化权限数据

大多数情况下权限管理通常需要从服务端获取权限数据,然后在前端通过权限对比以此控制页面、操作等等权限行为。约定在 src/app.ts 中导出 auth 对象,该对象包含从服务端异步获取初始化的权限数据,并且约定最终返回格式为 { initialAuth: { [key: string]: boolean } }

src/app.ts
import { defineAuthConfig } from '@ice/plugin-auth/types';

export const authConfig = defineAuthConfig(async () => {
// 模拟请求权限数据
// const data = (await fetch('/api/auth')).json();
return {
initialAuth: {
admin: true,
guest: false,
},
};
});

页面权限

如需对某些页面进行权限控制,只需在页面组件的 pageConfig 中配置准入权限即可。

import { definePageConfig } from 'ice';

export default function Home() {
return <div>Home</div>
}

export const pageConfig = definePageConfig(() => ({
// 当前用户是 admin 时,有权限访问该页面
auth: ['admin'],
}));

操作权限

在某些场景下,如某个组件中要根据角色判断是否有操作权限,我们可以通过 useAuth Hooks 在组件中获取权限数据,同时也可以更新初始的权限数据。

获取权限数据

import React from 'react';
import { useAuth } from 'ice';

function Foo() {
const [auth] = useAuth();
return (
<>
当前用户权限数据:
<code>{JSON.stringify(auth)}</code>
</>
);
}

设置权限数据

import React from 'react';
import { useAuth } from 'ice';

function Home() {
const [auth, setAuth] = useAuth();

// 更新权限,与默认的 auth 数据进行合并
function updateAuth() {
setAuth({ admin: false, guest: true });
}

return (
<>
当前用户角色:
<code>{JSON.stringify(auth)}</code>
<button type="button" onClick={updateAuth}>
更新权限
</button>
</>
);
}

自定义权限组件

对于操作类权限,通常我们可以自定义封装权限组件,以便更细粒度的控制权限和复用。

import React from 'react';
import { useAuth } from 'ice';
import NoAuth from '@/components/NoAuth';

function Auth({ children, authKey, fallback }) {
const [auth] = useAuth();
// 判断是否有权限
const hasAuth = auth[authKey];

// 有权限时直接渲染内容
if (hasAuth) {
return children;
} else {
// 无权限时显示指定 UI
return fallback || NoAuth;
}
}

export default Auth;

使用如下:

function Foo() {
return (
<Auth authKey={'starRepo'}>
<Button type="button">Star</Button>
</Auth>
);
}

自定义 Fallback

支持自定义无权限时的展示组件,默认为 <>No Auth</>

src/app.tsx
import { defineAuthConfig } from '@ice/plugin-auth/types';

export const authConfig = defineAuthConfig(async () => {
return {
initialAuth: {
admin: true,
},
+ NoAuthFallback: (routeConfig) => {
+ console.log(routeConfig); // 当前页面的配置
+ return (
+ <div>没有权限</div>
+ );
+ },
+ };
});