You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现SvelteKit受保护的shadow endpoints?避免冗余代码且保障安全

如何在验证Cookie中access_token的同时避免样板代码并保障安全

核心思路:用中间件/拦截器统一处理校验

把token验证逻辑抽成独立的中间件(或拦截器),指定需要保护的shadow endpoints必须经过这个中间件校验。验证通过才放行到业务逻辑,失败直接返回未授权响应——这样不用每个接口都重复写校验代码,完全解耦权限逻辑和业务逻辑。

不同技术栈的实现示例

1. Node.js + Express

先写通用的token校验中间件:

const jwt = require('jsonwebtoken');

const validateAccessToken = (req, res, next) => {
  // 从Cookie取token
  const accessToken = req.cookies.access_token;
  if (!accessToken) {
    return res.status(401).json({ error: '未提供访问令牌' });
  }

  try {
    // 校验token签名、过期时间等核心属性
    const decoded = jwt.verify(accessToken, process.env.JWT_SECRET);
    // 把解析后的用户信息挂载到req,后续接口直接用
    req.user = decoded;
    next(); // 验证通过,放行到业务接口
  } catch (err) {
    return res.status(401).json({ error: '令牌无效或已过期' });
  }
};

给shadow endpoints批量绑定中间件(用路由分组更高效):

const express = require('express');
const app = express();
const shadowRouter = express.Router();

// 给整个shadow路由组绑定校验中间件
shadowRouter.use(validateAccessToken);

// 具体的shadow接口,不用再写校验代码
shadowRouter.get('/data', (req, res) => {
  res.send(`仅授权用户${req.user.username}可见内容`);
});
shadowRouter.post('/update', (req, res) => {
  res.send('更新操作已执行');
});

// 挂载路由组
app.use('/shadow', shadowRouter);

// 公开接口无需校验
app.get('/public', (req, res) => res.send('公开内容'));

2. Python + FastAPI

用FastAPI的Depends实现依赖注入式校验,本质也是统一逻辑:

from fastapi import FastAPI, Depends, HTTPException, status
from jose import JWTError, jwt
from fastapi.requests import Request

app = FastAPI()

# 从Cookie提取token的依赖函数
def get_token_from_cookie(request: Request):
    token = request.cookies.get("access_token")
    if not token:
        raise HTTPException(status_code=401, detail="未找到访问令牌")
    return token

# 通用的token校验依赖
async def validate_token(token: str = Depends(get_token_from_cookie)):
    try:
        # 校验签名、过期时间、受众等
        payload = jwt.decode(token, "your-secret-key", algorithms=["HS256"])
        username = payload.get("sub")
        if not username:
            raise HTTPException(status_code=401, detail="令牌无效")
        return {"username": username}
    except JWTError:
        raise HTTPException(status_code=401, detail="令牌无效或已过期")

# shadow接口自动触发校验
@app.get("/shadow/data")
async def get_shadow_data(current_user: dict = Depends(validate_token)):
    return {"content": f"仅{current_user['username']}可访问"}

# 公开接口
@app.get("/public")
async def public():
    return {"content": "任何人都能看"}

3. Java Spring Boot

用拦截器批量拦截shadow路径:

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

@Component
public class AccessTokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从Cookie获取token
        String accessToken = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("access_token".equals(cookie.getName())) {
                    accessToken = cookie.getValue();
                    break;
                }
            }
        }

        if (accessToken == null) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未提供访问令牌");
            return false;
        }

        // 校验token的签名、过期时间等
        if (!validateToken(accessToken)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "令牌无效或已过期");
            return false;
        }

        // 把用户信息存入request,后续接口可直接获取
        request.setAttribute("currentUser", parseUserFromToken(accessToken));
        return true;
    }

    // 实际项目中替换为真实的token校验逻辑
    private boolean validateToken(String token) {
        // 校验签名、exp、iss等字段
        return true;
    }

    private Object parseUserFromToken(String token) {
        // 解析token中的用户信息
        return new Object();
    }
}

注册拦截器,指定拦截shadow路径:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final AccessTokenInterceptor accessTokenInterceptor;

    public WebConfig(AccessTokenInterceptor accessTokenInterceptor) {
        this.accessTokenInterceptor = accessTokenInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(accessTokenInterceptor)
                .addPathPatterns("/shadow/**") // 拦截所有shadow开头的接口
                .excludePathPatterns("/public/**"); // 排除公开接口
   </think_never_used_51bce0c785ca2f68081bfa7d91973934>
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:21:22