周三下午三点,你刚接手一个新项目。登录页、仪表盘、管理后台,路由保护又要写一遍。PrivateRoute组件,角色判断hook,HasAccess高阶组件——代码从上一个项目复制过来,改改变量名,祈祷别出bug。

这种事干了多少回了?

打开网易新闻 查看精彩图片

路由保护的业务逻辑永远一样:谁可以看什么,没权限去哪。但实现方式每个项目都不同。有人用React Router的loader,有人写高阶组件,有人直接在页面里判断。新人入职先花两天看懂这套"祖传代码",离职时再留下一套新的。

react-protected想终结这个循环。它不帮你做权限判断——那部分每个业务都不一样——但把"描述规则"和"执行检查"这两件事标准化了。

库拆成两个包。@react-protected/core是纯逻辑,不依赖React,也不绑任何路由。你在里面配好:怎么取当前用户、怎么验角色、怎么验权限、没登录去哪、没权限去哪。这部分可以单元测试,可以跨项目复用。

@react-protected/react-router是适配层,给React Router用。支持两种写法。

配置式适合喜欢集中管理的人:

const router = createGuardedRouter(

{ path: '/', element: },

{ path: '/login', element: , access: 'guest-only' },

{ path: '/dashboard', element: , access: 'authenticated' },

{ path: '/admin', element: , access: 'authenticated', roles: ['admin'] },

path: '/contracts',

element: ,

access: 'authenticated',

permissions: ['contracts:read'],

},

],

getUser: () => useAuthStore.getState().user,

hasRole: (user, roles) => roles.some((role) => user.roles.includes(role)),

hasPermission: (user, permissions) =>

permissions.every((p) => user.permissions.includes(p)),

loginPath: '/login',

forbiddenPath: '/403',

JSX式适合喜欢声明式组件的人:

getUser={() => useAuthStore.getState().user}

hasRole={(user, roles) => roles.some((role) => user.roles.includes(role))}

loginPath="/login"

forbiddenPath="/403"

path="/dashboard"

element={

两种模式支持同样的权限模型。RBAC传roles,ABAC传permissions,或者两者同时要求。验证逻辑你自己定:OR、AND、层级关系——业务需要什么就写什么。

不用React Router?core包可以直接对接任何框架。Next.js、Remix、或者自研路由,只要实现对应的适配层就行。