Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

middleware-protection中间件保护

Agent Skill

middleware-protection 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

717

周安装

29

GitHub Stars

777

下载量

225
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:middleware-protection(中间件保护)
来源仓库:https://github.com/dadbodgeoff/drift
仓库路径:skills/middleware-protection
安装命令:
npx skills add https://github.com/dadbodgeoff/drift --skill middleware-protection
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill middleware-protection

简介

用于中间件安全防护方案的检索与筛选。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

  • 适合查找鉴权、限流或防注入等保护机制。
  • 通过 GitHub 安装,建议核实维护状态与使用限制。
  • 使用时需注意是否涉及敏感操作或外部调用。
  • middleware-protection 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Middleware Route Protection

Check auth once, protect routes declaratively.

When to Use This Skill

  • Need to protect multiple routes
  • Want centralized auth checking
  • Tired of repeating auth logic in every route
  • Need role-based access control

Core Concepts

  1. Middleware intercepts - All requests pass through middleware
  2. Declarative routes - Define protected/public routes in config
  3. Session refresh - Keep sessions alive automatically
  4. Consistent errors - API routes get JSON, pages get redirects

TypeScript Implementation

middleware.ts

// middleware.ts
import { createServerClient } from '@supabase/ssr';
import { NextResponse, type NextRequest } from 'next/server';

// Routes that require authentication
const PROTECTED_ROUTES = [
  '/dashboard',
  '/settings',
  '/api/user',
  '/api/predictions',
];

// Routes that are always public
const PUBLIC_ROUTES = [
  '/',
  '/login',
  '/signup',
  '/api/health',
  '/api/public',
];

export async function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  // Skip static files and Next.js internals
  if (
    pathname.startsWith('/_next') ||
    pathname.startsWith('/favicon') ||
    pathname.match(/\.(svg|png|jpg|jpeg|gif|webp|ico)$/)
  ) {
    return NextResponse.next();
  }

  // Skip explicitly public routes
  if (PUBLIC_ROUTES.some(route => pathname === route || pathname.startsWith(route + '/'))) {
    return NextResponse.next();
  }

  // Create response that we'll modify
  let response = NextResponse.next({ request });

  // Create Supabase client with cookie handling
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll();
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) =>
            request.cookies.set(name, value)
          );
          response = NextResponse.next({ request });
          cookiesToSet.forEach(({ name, value, options }) =>
            response.cookies.set(name, value, options)
          );
        },
      },
    }
  );

  // Refresh session (important for SSR)
  const { data: { user } } = await supabase.auth.getUser();

  // Check if route requires auth
  const requiresAuth = PROTECTED_ROUTES.some(route =>
    pathname === route || pathname.startsWith(route + '/')
  );

  if (requiresAuth && !user) {
    // API routes: return 401 JSON
    if (pathname.startsWith('/api/')) {
      return NextResponse.json(
        {
          error: 'Authentication required',
          code: 'AUTH_REQUIRED',
          loginUrl: '/login',
        },
        { status: 401 }
      );
    }

    // Pages: redirect to login with return URL
    const url = request.nextUrl.clone();
    url.pathname = '/login';
    url.searchParams.set('redirectTo', pathname);
    return NextResponse.redirect(url);
  }

  // Add user ID to headers for downstream use
  if (user) {
    response.headers.set('x-user-id', user.id);
  }

  return response;
}

export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
};

Using User ID in API Routes

// app/api/user/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createServerSupabaseClient } from '@/lib/supabase-server';

export async function GET(request: NextRequest) {
  // User ID was added by middleware
  const userId = request.headers.get('x-user-id');

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const supabase = await createServerSupabaseClient();

  const { data: profile } = await supabase
    .from('user_profiles')
    .select('*')
    .eq('id', userId)
    .single();

  return NextResponse.json({ profile });
}

Role-Based Protection

// middleware.ts (extended)

const ROUTE_ROLES: Record<string, string[]> = {
  '/admin': ['admin'],
  '/dashboard': ['user', 'admin'],
  '/api/admin': ['admin'],
};

// After getting user, check role
if (user) {
  const userRole = user.user_metadata?.role || 'user';

  const requiredRoles = Object.entries(ROUTE_ROLES)
    .find(([route]) => pathname.startsWith(route))?.[1];

  if (requiredRoles && !requiredRoles.includes(userRole)) {
    if (pathname.startsWith('/api/')) {
      return NextResponse.json(
        { error: 'Forbidden', code: 'FORBIDDEN' },
        { status: 403 }
      );
    }
    return NextResponse.redirect(new URL('/unauthorized', request.url));
  }
}

Pattern-Based Routes

// For more complex route matching
const PROTECTED_PATTERNS = [
  /^\/dashboard(\/.*)?$/,
  /^\/api\/user\/.*$/,
  /^\/settings$/,
  /^\/api\/v\d+\/private\/.*/,  // /api/v1/private/*, /api/v2/private/*
];

const requiresAuth = PROTECTED_PATTERNS.some(pattern =>
  pattern.test(pathname)
);

Python Implementation (FastAPI)

# middleware/auth.py
from fastapi import Request, HTTPException
from fastapi.responses import RedirectResponse
from starlette.middleware.base import BaseHTTPMiddleware
from typing import Set

PROTECTED_ROUTES: Set[str] = {
    "/dashboard",
    "/settings",
    "/api/user",
}

PUBLIC_ROUTES: Set[str] = {
    "/",
    "/login",
    "/signup",
    "/api/health",
}

class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        path = request.url.path

        # Skip public routes
        if path in PUBLIC_ROUTES or any(path.startswith(r + "/") for r in PUBLIC_ROUTES):
            return await call_next(request)

        # Check if route requires auth
        requires_auth = path in PROTECTED_ROUTES or any(
            path.startswith(r + "/") for r in PROTECTED_ROUTES
        )

        if not requires_auth:
            return await call_next(request)

        # Get user from session/token
        user = await get_user_from_request(request)

        if not user:
            if path.startswith("/api/"):
                raise HTTPException(
                    status_code=401,
                    detail={
                        "error": "Authentication required",
                        "code": "AUTH_REQUIRED",
                        "login_url": "/login",
                    }
                )
            return RedirectResponse(f"/login?redirectTo={path}")

        # Add user to request state
        request.state.user = user
        request.state.user_id = user.id

        return await call_next(request)

async def get_user_from_request(request: Request):
    """Extract and validate user from request."""
    token = request.cookies.get("session") or request.headers.get("Authorization")
    if not token:
        return None
    # Validate token and return user
    return await validate_session(token)
# Using in routes
from fastapi import Request, Depends

@app.get("/api/user/profile")
async def get_profile(request: Request):
    user_id = request.state.user_id
    profile = await db.get_profile(user_id)
    return {"profile": profile}

Error Response Format

// Consistent error format for API routes
interface AuthError {
  error: string;
  code: 'AUTH_REQUIRED' | 'SESSION_EXPIRED' | 'FORBIDDEN';
  message?: string;
  loginUrl: string;
}

// 401 - Not authenticated
{
  "error": "Authentication required",
  "code": "AUTH_REQUIRED",
  "loginUrl": "/login"
}

// 403 - Authenticated but not authorized
{
  "error": "Forbidden",
  "code": "FORBIDDEN",
  "message": "Admin access required"
}

Best Practices

  1. Refresh sessions - Call getUser() in middleware to refresh
  2. Pass user ID - Add to headers for downstream routes
  3. JSON for APIs - Never redirect API routes
  4. Return URL - Include redirectTo param for login redirects
  5. Skip static - Don't process static files

Common Mistakes

  • Redirecting API routes (should return 401 JSON)
  • Not refreshing session in middleware
  • Processing static files through auth
  • Missing return URL on login redirect
  • Not handling role-based access

Related Skills

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.68%
按下载量换算87

Claude

28.94%
按下载量换算65

Cursor

17.91%
按下载量换算40

Gemini CLI

8.73%
按下载量换算20

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills