安全 Hook 与路由守卫
SecurityProvider 要求现有 TokenStorage 和 children,通过 context 提供 useSecurity 状态。令牌创建/刷新由 CoSec 负责;路由守卫仅决定渲染哪个 React 节点,不是服务端授权边界。
| API | 契约 |
|---|---|
useSecurity(tokenStorage, options = {}) | 返回 currentUser、authenticated、signIn、signOut;无令牌使用 ANONYMOUS_USER,其 sub 为 anonymous、jti 为空、iat/exp 为零。authenticated(access token 未过期)在渲染时计算;refresh token 到期时 Hook 会重新渲染,闲置页面随之退出登录,而仍可续期的会话由下一个请求续期。 |
signIn(tokenOrAsyncProvider) | 如有 provider 则等待,存储令牌,再调用 onSignIn;返回 Promise<void>,provider/存储/回调失败会传播。 |
signOut() | 删除令牌并调用 onSignOut;同步异常传播。 |
useSecurityContext() | 返回上下文,在 SecurityProvider 外抛错。 |
RouteGuard | 已认证渲染 children;否则返回 fallback(省略则无内容),并在提交后调用 onUnauthorized。 |
RefreshableRouteGuard | 必填 tokenManager;isRefreshNeeded 和 isRefreshable 同时成立时刷新。已认证优先渲染 children,否则刷新期间显示 refreshing 节点,无法刷新或刷新失败时显示 fallback,默认文字 Refreshing...。 |
RouteGuard.onUnauthorized 在 render 提交后的 effect 中运行,每次 authenticated 变为(或初始即为)false 时调用一次,因此可以在其中调用 navigate();开发环境的 StrictMode 可能像对待任何 effect 一样运行两次。使用的是最新的回调;仅回调变化不会再次调用。RefreshableRouteGuard 仅记录刷新失败,不暴露本地错误状态,也不在卸载时取消 token manager;manager 和 storage 仍归应用所有。context 随存储订阅更新,没有独立每秒重算认证状态的定时器。切换 tokenStorage 会更换订阅和操作目标;回调读取最新 options。
完整示例
import type { TokenStorage } from '@ahoo-wang/fetcher-cosec';
import {
SecurityProvider,
RouteGuard,
useSecurityContext,
} from '@ahoo-wang/fetcher-react';
function Account() {
const { currentUser, signOut } = useSecurityContext();
return <button onClick={signOut}>Sign out {currentUser.sub}</button>;
}
export function SecureApp({ storage }: { storage: TokenStorage }) {
return (
<SecurityProvider tokenStorage={storage}>
<RouteGuard fallback={<p>Please sign in.</p>}>
<Account />
</RouteGuard>
</SecurityProvider>
);
}公开签名与类型
以下签名按当前根入口可达声明核对。? 表示可省略;泛型/接口只约束编译期,继承项与关联类型可从 符号索引 定位。运行时默认值和失败行为以本页上文为准。
SecurityProvider
export function SecurityProvider(
options: SecurityContextOptions,
): import('react').JSX.Element;packages/react/src/cosec/SecurityContext.tsx:107
useSecurityContext
export function useSecurityContext(): SecurityContextValue;packages/react/src/cosec/SecurityContext.tsx:146
SecurityContextValue
export type SecurityContextValue = UseSecurityReturn;packages/react/src/cosec/SecurityContext.tsx:30
SecurityContext
declare const SecurityContext: import('react').Context<
UseSecurityReturn | undefined
>;packages/react/src/cosec/SecurityContext.tsx:41
SecurityContextOptions
export interface SecurityContextOptions extends UseSecurityOptions {
tokenStorage: TokenStorage;
children: ReactNode;
}packages/react/src/cosec/SecurityContext.tsx:49
useSecurity
export function useSecurity(
tokenStorage: TokenStorage,
options?: UseSecurityOptions,
): UseSecurityReturn;实现默认值: options = {}.
packages/react/src/cosec/useSecurity.ts:155
ANONYMOUS_USER
declare const ANONYMOUS_USER: CoSecJwtPayload;packages/react/src/cosec/useSecurity.ts:29
UseSecurityOptions
export interface UseSecurityOptions {
onSignIn?: () => void;
onSignOut?: () => void;
}packages/react/src/cosec/useSecurity.ts:39
UseSecurityReturn
export interface UseSecurityReturn {
currentUser: CoSecJwtPayload;
authenticated: boolean;
signIn: (compositeTokenProvider: CompositeTokenProvider) => Promise<void>;
signOut: () => void;
}packages/react/src/cosec/useSecurity.ts:56
RouteGuard
展开完整字段与成员
export function RouteGuard(
options: RouteGuardProps,
):
| string
| number
| bigint
| boolean
| import('react').JSX.Element
| Iterable<ReactNode>
| Promise<
| string
| number
| bigint
| boolean
| import('react').ReactPortal
| import('react').ReactElement<
unknown,
string | import('react').JSXElementConstructor<any>
>
| Iterable<ReactNode>
| null
| undefined
>
| null
| undefined;packages/react/src/cosec/RouteGuard.tsx:69
RouteGuardProps
export interface RouteGuardProps {
children: ReactNode;
fallback?: ReactNode;
onUnauthorized?: () => void;
}packages/react/src/cosec/RouteGuard.tsx:21
RefreshableRouteGuard
export function RefreshableRouteGuard(
options: RefreshableRouteGuardProps,
): import('react').JSX.Element;packages/react/src/cosec/RefreshableRouteGuard.tsx:28
RefreshableRouteGuardProps
export interface RefreshableRouteGuardProps extends Omit<
RouteGuardProps,
'onUnauthorized'
> {
refreshing?: ReactNode;
tokenManager: JwtTokenManager;
}packages/react/src/cosec/RefreshableRouteGuard.tsx:20
相关专题
Fetcher 请求 Hook · Promise 与查询状态 · API Hook 工厂 · 防抖执行 · 存储与事件订阅 · 最新值与稳定值
