Astro项目中静态预渲染动态路由的中间件权限保护问题
问题解答
核心结论
静态预渲染页面(设置export const prerender = true)无法正常使用依赖请求上下文(如Astro.request.headers、Cookie)的中间件。
问题原因分析
/preloads/*(|/)规则下未登录可访问:
该路由下的页面是静态预渲染的,构建时中间件仅执行一次,此时没有用户请求的Cookie或动态请求头,权限校验逻辑直接失效,未登录用户也能访问静态生成的页面内容。改为
/preloads/*后已登录用户无法访问:
静态预渲染页面构建完成后,请求时不会触发服务端中间件运行,而你的中间件代码试图访问Astro.request.headers——这个对象仅在服务端运行时(非预渲染页面)存在,静态模式下调用会直接抛出错误,导致页面加载失败。
可行解决方案
方案1:放弃静态预渲染(推荐)
删除该动态路由文件中的export const prerender = true,让页面走服务端渲染流程(你的项目已配置output: "server",默认支持)。此时每次请求都会触发中间件执行,能正常获取Cookie和请求上下文,权限校验逻辑可以正常工作。方案2:客户端侧权限校验(需静态预渲染时用)
如果必须保留静态预渲染,将权限校验逻辑移到页面组件的客户端代码中:--- import { createClient } from '@supabase/auth-helpers-astro'; --- <script> const supabase = createClient(); async function checkAuth() { const { data: { session } } = await supabase.auth.getSession(); if (!session) { window.location.href = '/login'; } } checkAuth(); </script>注意:这种方式是页面加载后再校验,会有短暂的内容闪烁,建议配合骨架屏或loading状态优化体验。
方案3:中间件排除静态路由
修改中间件的匹配规则,跳过静态预渲染的路由,仅对服务端渲染的路由做权限校验,静态路由单独用客户端逻辑处理:// middleware.ts export const onRequest = async ({ request, redirect }) => { // 排除静态预渲染的/preloads路由 if (new URL(request.url).pathname.startsWith('/preloads')) { return; } // 其他路由的权限校验逻辑 const session = await getSupabaseSession(request); if (!session) { return redirect('/login'); } };
内容的提问来源于stack exchange,提问作者petoma
相关产品推荐
相关产品推荐

