资讯动态

Refine 认证实战:用 authProvider 的 check 方法与 <Authenticated /> 组件保护页面内容

发布时间:2026/9/13 12:21:48 来源:尧图企业网站定制
Refine 认证实战用 authProvider 的 check 方法与 组件保护页面内容【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇基于 Refine 官方教程的 “Protecting Content” 步骤展开讲解如何为管理后台应用接入一个基础的authProvider并通过其check方法校验登录态再使用Authenticated /组件把应用内容从“未登录用户”手中隔离出来。读完后你能够完整实现一个最小可用的登录态校验方案创建src/providers/auth-provider.ts、把authProvider挂到Refine /上、实现check方法读取本地 token以及理解Authenticated /组件在源码层面的渲染与重定向分支逻辑。认证接入的整体思路Refine 对认证方案做了刻意解耦它不内置任何具体的登录实现而是通过一个接口简洁的authProvider约定来对接任意认证系统自建 REST API、Auth0、Supabase、NextAuth 等都可以在该接口下适配。authProvider接口由四个必选方法和若干可选方法组成官方支持清单可在 Authentication 文档 中查阅本教程示例则基于一个自带简单认证端点的假 REST API。从源码结构看AuthProvider接口的完整定义位于 types.tsexport type AuthProvider { login: (params: any) PromiseAuthActionResponse; logout: (params: any) PromiseAuthActionResponse; check: (params?: any) PromiseCheckResponse; onError: (error: any) PromiseOnErrorResponse; register?: (params: any) PromiseAuthActionResponse; forgotPassword?: (params: any) PromiseAuthActionResponse; updatePassword?: (params: any) PromiseAuthActionResponse; getPermissions?: (params?: Recordstring, any) PromisePermissionResponse; getIdentity?: (params?: any) PromiseIdentityResponse; };即login、logout、check、onError四个方法是必填的register、forgotPassword、updatePassword、getPermissions、getIdentity是可选扩展。本步骤聚焦其中与“内容保护”直接相关的check方法login/logout会在教程后续步骤补全所以先抛出Not implemented占位。check方法的返回值类型同样在 types.ts 中定义export type CheckResponse { authenticated: boolean; redirectTo?: string; // 未认证时的重定向目标 logout?: boolean; // 是否需要触发登出 error?: RefineError | Error; };其中redirectTo字段与Authenticated /组件的redirectOnFail行为直接相关见下文。创建 Auth Provider 并接入第一步是在项目中创建src/providers/auth-provider.ts文件作为认证逻辑的统一存放位置。接着把 auth provider 通过authProvider属性传给src/App.tsx中的Refine /组件import { Refine } from refinedev/core; import { dataProvider } from ./providers/data-provider; import { authProvider } from ./providers/auth-provider; import { ShowProduct } from ./pages/products/show; import { EditProduct } from ./pages/products/edit; import { ListProducts } from ./pages/products/list; import { CreateProduct } from ./pages/products/create; export default function App(): JSX.Element { return ( Refine dataProvider{dataProvider} authProvider{authProvider} {/* ShowProduct / */} {/* EditProduct / */} ListProducts / {/* CreateProduct / */} /Refine ); }authProvider一旦传入Refine 内部就会用AuthProviderContextProvider包裹应用。该 Provider 的实现位于 contexts/auth/index.tsx它对每个方法都包了一层 try/catch 并暴露给 React Context。值得注意的两个源码细节Refine 期望 auth 方法总是返回已 resolve 的 Promise。handleCheck等包装函数在 catch 分支中会打印Unhandled Error in check: refine always expects a resolved promise.的警告——这也是 types.ts 顶部大段注释所阐述的设计意图check即使判定用户未登录也应 resolve 出{ authenticated: false, ... }这类携带决策信息的对象而不是 rejectlogout成功后会自动调用queryClient.invalidateQueries()见 index.tsx用于清理 React Query 缓存中可能残留的旧用户数据这是handleLogout与其他包装函数的一个显著区别。实现 check 方法check方法被useIsAuthenticated钩子和Authenticated /组件共同消费用于判断用户当前是否已登录。它应返回一个 Promiseresolve 值为对象用户已登录时包含authenticated: true否则包含authenticated: false。教程示例的认证凭据策略是登录时通过 API 换取 access token 并存入localStorage因此check只需检查本地是否存在该 tokenimport { AuthProvider } from refinedev/core; export const authProvider: AuthProvider { check: async () { // When logging in, well obtain an access token from our API and store it in the local storage. // Now lets check if the token exists in the local storage. // In the later steps, well be implementing the login and logout methods. const token localStorage.getItem(my_access_token); return { authenticated: Boolean(token) }; }, login: async ({ email, password }) { throw new Error(Not implemented); }, logout: async () { throw new Error(Not implemented); }, onError: async (error) { throw new Error(Not implemented); }, // ... };两个实现要点token 键名为my_access_token这是本教程约定的存储键后续login/logout方法会围绕同一键写入与清除保持一致性返回完整对象而非裸布尔值虽然示例只用了authenticated但结合CheckResponse类型可知check还可以返回redirectTo未登录时希望跳转的页面与logout是否需要触发登出流程。types.ts 的注释给出了组合语义的例子{ authenticated: false, logout: false, redirect: /not-authenticated }表示不登出但跳转{ authenticated: false, logout: true, redirect: false }表示登出但不跳转。这让认证决策权保留在你的 auth provider 中而不是写死在框架里。使用 组件保护内容实现check后就可以用Authenticated /组件把需要登录的内容包起来。更新src/App.tsx在Refine /内部用Authenticated /包裹页面内容并提供未登录时的fallbackimport { Refine, Authenticated } from refinedev/core; import { dataProvider } from ./providers/data-provider; import { authProvider } from ./providers/auth-provider; import { ShowProduct } from ./pages/products/show; import { EditProduct } from ./pages/products/edit; import { ListProducts } from ./pages/products/list; import { CreateProduct } from ./pages/products/create; export default function App(): JSX.Element { return ( Refine dataProvider{dataProvider} authProvider{authProvider} Authenticated keyprotected fallback{divNot authenticated/div} {/* ShowProduct / */} {/* EditProduct / */} ListProducts / {/* CreateProduct / */} /Authenticated /Refine ); }两个容易忽略的细节key属性是必需的。教程特别强调当同一渲染树中出现多个Authenticated /实例时必须为每个实例提供唯一key。Authenticated 组件源码 的属性定义中key被标记为requiredfallback决定未登录时的展示。只要设置了fallback未认证用户看到的就是这段内容组件不会执行重定向。此时运行应用由于 localStorage 中还没有my_access_tokencheck会返回{ authenticated: false }页面内容不会渲染取而代之的是fallback中的Not authenticated文本——这正是“内容受保护”的直观表现。源码视角下的 分支逻辑Authenticated /的完整实现位于 components/authenticated/index.tsx其属性签名包含本步骤用到的fallback以及几个未用到但值得了解的行为开关export type AuthenticatedProps { key: React.Key; // 同一层级多个实例时必传 redirectOnFail?: string | true; // 默认 true未登录时的重定向目标 appendCurrentPathToQuery?: boolean; // 默认 true fallback?: React.ReactNode; // 未登录时渲染的内容 loading?: React.ReactNode; // check 进行中渲染的内容 children?: React.ReactNode; // 已登录时渲染的内容 params?: AuthCheckParams; // 透传给 check 方法的参数 };组件的渲染决策按如下顺序执行见 index.tsx未提供 authProvider视为无认证约束直接渲染children正在执行 checkisFetching渲染loading无则渲染空已认证渲染children未认证且设置了fallback渲染fallback本教程即命中此分支未认证且未设置fallback执行重定向。目标地址优先取redirectOnFail的字符串值否则回退到check响应中的redirectTo同时默认把当前路径以to查询参数追加到重定向 URL 上appendCurrentPathToQuery控制从而在登录成功后能回到用户原本要访问的页面。这套分支解释了为什么教程示例使用fallback而非重定向fallback的优先级高于redirectOnFail源码注释也明确 “This property only works iffallbackis not set”。useIsAuthenticated组件底层的钩子实现教程提示也可以直接使用Authenticated /组件底层使用的useIsAuthenticated钩子。其实现位于 hooks/auth/useIsAuthenticated/index.tsconst queryResponse useQueryCheckResponse({ queryKey: keys().auth().action(check).get(), queryFn: async () (await check?.(params)) ?? { authenticated: true }, retry: false, ...queryOptions, // ... });从源码结构看有三个值得注意的实现细节基于 TanStack React Query 封装check的结果会进入 React Query 缓存queryKey 为auth/check应用内多处消费时不会重复发起校验retry: false登录态校验失败不自动重试避免无效轮询未提供 check 时的兜底值若authProvider.check未实现queryFn 返回{ authenticated: true }即默认放行。配合Authenticated /中“无 authProvider 直接渲染 children”的分支说明 Refine 允许应用存在“可选认证”的形态——这与其 types.ts 注释中 “Apps can exist with an optional auth” 的设计意图一致。钩子的返回类型是UseQueryResultCheckResponse因此可以直接解构出isFetching、data?.authenticated、data?.redirectTo等字段做自定义渲染而不必局限于Authenticated /的组件形态。小结与下一步本步骤完成了内容保护的最小闭环环节产出说明Provider 文件src/providers/auth-provider.ts集中实现 auth 方法当前实现check其余方法占位应用接线src/App.tsx传入authProviderRefine /通过 Context 向全局暴露认证能力登录态校验check读取my_access_token返回{ authenticated: Boolean(token) }内容隔离Authenticated key fallback未登录渲染 fallback已登录渲染子内容此时应用的表现是未登录用户只能看到Not authenticated占位产品列表等受保护内容不可见。在教程的 下一步user-identity 中将实现login与logout方法让check的 token 检查真正跑通并补充用户身份信息展示后续还会把认证逻辑与 data provider 的集成如请求头携带 token串起来。若想回顾认证接入的起点可参见 tutorial 认证介绍。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价