前端安全

Zero Trust Security Model: Never Trust, Always Verify

The security landscape in 2026 is more challenging than ever. The traditional "castle and moat" model — trusting internal networks while distrusting external ones — has completely failed. Zero trust security emerges with one core principle:

Never Trust, Always Verify

Every request, every interaction, every data packet must undergo strict authentication and authorization checks regardless of its origin. There is no "trusted zone" and no "implicit trust."


Traditional Perimeter Security vs Zero Trust Architecture

Dimension Perimeter Security Zero Trust
Trust Model Internal trusted, external untrusted All requests untrusted
Verification One-time login Per-request verification
Network Boundary Firewall/VPN dependent No boundary, identity is boundary
Attack Surface Lateral movement after breach Every step re-verified
Best For Monolithic apps Cloud-native/Microservices
Frontend Assumes "safe zone" Frontend is untrusted terminal

The critical flaw of the traditional model: once attackers breach the perimeter, they can move laterally without restriction. Under zero trust, even if an attacker obtains a token, they cannot impersonate the user long-term because every operation requires re-verification.


Frontend Zero Trust: Independent Verification Per Request

The frontend is the most critical component in zero trust architecture because frontend code runs in the user's browser — a completely uncontrollable environment.

Core Principles

  1. No Implicit Trust: Don't trust subsequent requests just because the user is logged in
  2. Least Privilege: Each request gets only the minimum permissions needed
  3. Continuous Verification: Short-lived tokens, frequent refresh
  4. Assume Breach: Design assuming attackers already control the frontend

Request-Level Verification

class ZeroTrustHttpClient {
  private tokenManager: TokenManager;
  private proofManager: DPoPProofManager;

  async request(config: RequestConfig): Promise<Response> {
    const token = await this.tokenManager.getValidToken();
    const proof = await this.proofManager.generateProof(
      config.method,
      config.url
    );

    const response = await fetch(config.url, {
      method: config.method,
      headers: {
        'Authorization': `DPoP ${token}`,
        'DPoP': proof,
        'X-Request-ID': crypto.randomUUID(),
        'X-Timestamp': Date.now().toString(),
      },
      body: config.body,
    });

    if (response.status === 401) {
      await this.tokenManager.refreshToken();
      return this.request(config);
    }

    return response;
  }
}

Token Security: JWT Best Practices

Practice Description Risk Level
Short-lived Access Token TTL ≤ 5 minutes 🔴 Critical
HttpOnly Cookie Storage Prevents XSS theft 🔴 Critical
Refresh Token Rotation New refresh token on each refresh 🔴 Critical
Token Binding (DPoP) Bind token to key pair 🟡 Important
Audience Restriction Limit token usage target 🟡 Important
Issuer Validation Verify token issuer 🟢 Recommended
JTI Dedup Prevent token replay 🟢 Recommended

DPoP: Demonstration of Proof-of-Possession

DPoP binds the token to the client's key pair. Even if an attacker steals the token, they cannot use it without the corresponding private key:

class DPoPProofManager {
  private keyPair: CryptoKeyPair | null = null;

  async init(): Promise<void> {
    this.keyPair = await crypto.subtle.generateKey(
      { name: 'ECDSA', namedCurve: 'P-256' },
      false,
      ['sign']
    );
  }

  async generateProof(method: string, url: string): Promise<string> {
    if (!this.keyPair) throw new Error('Key pair not initialized');

    const header = { typ: 'dpop+jwt', alg: 'ES256', jwk: await this.getPublicKey() };
    const payload = {
      htu: new URL(url).origin + new URL(url).pathname,
      htm: method,
      iat: Math.floor(Date.now() / 1000),
      jti: crypto.randomUUID(),
    };

    return this.signJWT(header, payload);
  }
}

Runtime Protection: CSP, Trusted Types, and SRI

Strict CSP Policy

<meta http-equiv="Content-Security-Policy" content="
  default-src 'none';
  script-src 'strict-dynamic' 'nonce-abc123';
  style-src 'self' 'nonce-abc123';
  img-src 'self' https: data:;
  font-src 'self';
  connect-src 'self' https://api.example.com;
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  require-trusted-types-for 'script';
  report-uri /api/csp-report;
">

Trusted Types for XSS Prevention

if (window.trustedTypes) {
  const sanitizer = trustedTypes.createPolicy('default', {
    createHTML: (input: string) => {
      return DOMPurify.sanitize(input, {
        ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
        ALLOWED_ATTR: ['href', 'target'],
      });
    },
    createScriptURL: (input: string) => {
      const allowed = ['https://cdn.example.com/'];
      if (allowed.some(origin => input.startsWith(origin))) return input;
      throw new Error('Untrusted script URL blocked');
    },
    createScript: () => { throw new Error('createScript is not allowed'); },
  });
}

Subresource Integrity (SRI)

<script
  src="https://cdn.example.com/lib/v2.3.1/bundle.js"
  integrity="sha384-oc5F5A5B7B6B8B9C0D1E2F3G4H5I6J7K8L9M0N1O2P3Q4R5S6T7U8V9W0X1Y2Z3"
  crossorigin="anonymous"
></script>

Supply Chain Security

# Audit for known vulnerabilities
npm audit --audit-level=high

# Validate lockfile integrity
npm ci --ignore-scripts

# Generate SBOM
npx @cyclonedx/cyclonedx-npm --output-format json -o sbom.json

Best practice: Generate SBOM on every CI build and automatically compare against vulnerability databases (OSV, NVD).


Zero Trust Frontend Architecture Checklist

Authentication & Authorization

  • Access Token TTL ≤ 5 minutes
  • Refresh Token rotation enabled
  • Token stored in HttpOnly + Secure + SameSite=Strict cookie
  • DPoP token binding enabled
  • Each API request carries unique Request ID and timestamp

Runtime Protection

  • CSP set to default-src 'none' whitelist mode
  • Trusted Types policy configured
  • All CDN resources use SRI
  • eval(), new Function(), document.write() disabled

Supply Chain

  • npm audit integrated into CI pipeline
  • Lockfile integrity validation enabled
  • SBOM generated on each build
  • Dependency changes require Code Review approval

Monitoring & Response

  • CSP violation reporting with real-time alerts
  • Token anomaly detection (multi-location login, frequency anomalies)
  • Incident response plan for token leaks

Zero trust is not a product — it's a security mindset. It requires re-examining every trust assumption in frontend applications, shifting from "default trust" to "default deny, explicitly allow."

Try these browser-local tools — no sign-up required →

#零信任#前端安全#Token验证#CSP#微前端安全