Next.js页面角色权限自动化配置及预加载校验问题解决
Next.js 页面权限前置校验方案
需求
路由信息变更时,需先完成用户角色获取与校验,再决定是否进入目标页面:
- 权限匹配:加载页面并允许访问
- 无权限:直接重定向至错误页面,不加载目标页面
需实现一套算法,管控user_app下所有页面的访问权限。
现有流程
- 用户访问页面时,获取当前路径信息
- 通过路径从
process.env中读取该页面的权限配置 - 从Cookie/Token中提取用户角色信息
- 对比用户角色与页面权限,有权限则允许访问,无权限则重定向至404页面
当前问题
当前控制逻辑在用户进入页面后触发,校验函数执行期间目标页面会短暂可访问,需实现页面加载前的权限校验,通过后再加载页面数据。
解决方案(基于Next.js路由拦截)
在Next.js中,要彻底解决页面闪烁问题,需利用服务端或路由拦截能力在页面渲染前完成校验。以下针对Page Router场景给出改造方案:
核心思路
- 封装独立的权限校验工具函数,统一处理角色校验逻辑
- 利用
getServerSideProps(SSR场景)实现服务端前置校验,直接在服务端完成重定向 - 可选配置客户端路由监听,作为服务端校验的补充
代码实现
1. 封装权限校验工具函数
// utils/roleCheck.js import axios from 'axios'; import decrypted from '../crypto/decrypted'; export async function checkUserRole(path) { // 获取当前页面的权限配置 const pageRoles = process.env.pageLinks[path]; // 无权限配置默认拒绝访问 if (!pageRoles) { return { hasPermission: false }; } try { const res = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/token/GET`); // 存在有效用户信息时校验角色 if (res.data.success && res.data.Acoount != null) { const decryptedValue = decrypted(res.data.Acoount); const userRole = decryptedValue.role; // 权限匹配逻辑:用户角色在允许列表中,且不是公开页面(0代表公开)或路径为根目录 const hasPermission = pageRoles.includes(userRole) && (!pageRoles.includes(0) || path === "/"); return { hasPermission }; } else { // 无用户信息时,检查是否为公开页面 return { hasPermission: pageRoles.includes(0) }; } } catch (error) { console.error('权限校验失败:', error); return { hasPermission: false }; } }
2. 页面级前置校验(服务端)
在user_app下的所有页面组件中添加getServerSideProps,实现页面渲染前的服务端校验:
// pages/user_app/target-page.js(示例页面) import React from 'react'; import { checkUserRole } from '../../utils/roleCheck'; const TargetPage = () => { return <div>有权限访问的页面内容</div>; }; export async function getServerSideProps(context) { const { res } = context; const path = context.resolvedUrl; const { hasPermission } = await checkUserRole(path); if (!hasPermission) { // 服务端直接重定向到404,避免客户端页面加载 res.writeHead(302, { Location: '/404' }); res.end(); return { props: {} }; } return { props: {}, // 传递给页面组件的参数 }; } export default TargetPage;
3. 全局路由拦截(客户端补充)
如果需要统一管控所有页面,可在_app.js中监听路由变更事件,作为服务端校验的补充:
// pages/_app.js import { useEffect } from 'react'; import { useRouter } from 'next/router'; import { checkUserRole } from '../utils/roleCheck'; function MyApp({ Component, pageProps }) { const router = useRouter(); useEffect(() => { const handleRouteChange = async (url) => { // 避免重复校验404页面 if (url === '/404') return; const { hasPermission } = await checkUserRole(url); if (!hasPermission) { router.replace('/404'); } }; // 监听路由开始变更事件 router.events.on('routeChangeStart', handleRouteChange); return () => { // 组件卸载时移除监听 router.events.off('routeChangeStart', handleRouteChange); }; }, [router]); return <Component {...pageProps} />; } export default MyApp;
关键说明
- 服务端校验优先:
getServerSideProps能在页面渲染前完成校验,彻底避免页面闪烁问题 - 权限配置准确性:确保
process.env.pageLinks中的路径与实际页面路径完全匹配 - 异常处理:网络请求失败时默认拒绝访问,防止未授权用户绕过校验
内容的提问来源于stack exchange,提问作者Enes Gülcü
相关产品推荐
相关产品推荐

