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

React(TypeScript)无AD认证下如何获取Blob的SAS URL/SAS令牌?

Secure SAS URL Generation for Your React/TS App (No AD Auth)

Got it, since your React/TypeScript app isn’t using AD authentication, you can’t generate SAS URLs directly in the frontend—that would expose your storage account keys, which is a huge security red flag. Instead, you’ll need a backend service to handle the SAS generation safely, with your frontend only requesting the pre-signed URL when needed. Here’s a step-by-step implementation:


Step 1: Build a Backend Proxy (Node.js + TS Example)

We’ll use a simple Express backend to interact with your storage service (I’ll assume Azure Blob Storage here, since SAS is most commonly used with Azure; adjust the SDK if you’re using another provider like AWS S3).

Install Dependencies

npm install @azure/storage-blob dotenv express cors
npm install -D typescript @types/express @types/cors @types/node

Backend Code (server.ts)

import { BlobServiceClient, generateBlobSASQueryParameters, BlobSASPermissions } from "@azure/storage-blob";
import dotenv from "dotenv";
import express from "express";
import cors from "cors";

dotenv.config();
const app = express();

// Allow CORS from your frontend domain (replace with your actual URL in production)
app.use(cors({ origin: "http://localhost:3000" }));
app.use(express.json());

// Load storage credentials from environment variables (never hardcode these!)
const STORAGE_ACCOUNT_NAME = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const STORAGE_ACCOUNT_KEY = process.env.AZURE_STORAGE_ACCOUNT_KEY!;
const CONTAINER_NAME = process.env.AZURE_BLOB_CONTAINER_NAME!;

// Endpoint to generate and return SAS URL
app.post("/api/get-sas-url", async (req, res) => {
  const { documentName } = req.body;

  if (!documentName) {
    return res.status(400).json({ error: "Document name is required" });
  }

  try {
    // Initialize blob service client
    const blobServiceClient = BlobServiceClient.fromConnectionString(
      `DefaultEndpointsProtocol=https;AccountName=${STORAGE_ACCOUNT_NAME};AccountKey=${STORAGE_ACCOUNT_KEY};EndpointSuffix=core.windows.net`
    );
    const containerClient = blobServiceClient.getContainerClient(CONTAINER_NAME);
    const blobClient = containerClient.getBlobClient(documentName);

    // Configure SAS permissions and expiration (adjust based on your needs)
    const sasConfig = {
      containerName: CONTAINER_NAME,
      blobName: documentName,
      permissions: BlobSASPermissions.parse("r"), // Read-only access
      expiresOn: new Date(Date.now() + 3600 * 1000), // Expire after 1 hour
    };

    // Generate SAS token
    const sasToken = generateBlobSASQueryParameters(
      sasConfig,
      STORAGE_ACCOUNT_KEY,
      STORAGE_ACCOUNT_NAME
    ).toString();

    // Combine blob URL with SAS token
    const sasUrl = `${blobClient.url}?${sasToken}`;

    res.json({ sasUrl });
  } catch (err) {
    console.error("Failed to generate SAS URL:", err);
    res.status(500).json({ error: "Could not generate SAS URL" });
  }
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Backend running on port ${PORT}`);
});

Environment Variables (.env)

AZURE_STORAGE_ACCOUNT_NAME=your-storage-account-name
AZURE_STORAGE_ACCOUNT_KEY=your-storage-account-key
AZURE_BLOB_CONTAINER_NAME=your-container-name

Step 2: Frontend React/TS Implementation

Now, update your React app to pull the document name from query parameters and request the SAS URL from your backend.

import { useEffect, useState } from "react";

const DocumentManager = () => {
  const [sasUrl, setSasUrl] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  useEffect(() => {
    // Extract document name from query parameters
    const searchParams = new URLSearchParams(window.location.search);
    const documentName = searchParams.get("documentName");

    if (documentName) {
      fetchSasUrl(documentName);
    } else {
      setErrorMessage("No document name found in URL query parameters");
    }
  }, []);

  const fetchSasUrl = async (docName: string) => {
    try {
      const response = await fetch("http://localhost:3001/api/get-sas-url", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ documentName: docName }),
      });

      if (!response.ok) {
        throw new Error("Failed to retrieve SAS URL");
      }

      const data = await response.json();
      setSasUrl(data.sasUrl);

      // Do something with the SAS URL here (e.g., preview, download)
      console.log("Ready to use SAS URL:", data.sasUrl);
    } catch (err) {
      setErrorMessage(err instanceof Error ? err.message : "Unknown error occurred");
    }
  };

  return (
    <div className="document-manager">
      {errorMessage && <p className="error">{errorMessage}</p>}
      {sasUrl && (
        <div>
          <h3>SAS URL Generated</h3>
          <p>{sasUrl}</p>
          {/* Add your后续处理 logic here */}
        </div>
      )}
    </div>
  );
};

export default DocumentManager;

Critical Security & Best Practices

  • Never expose storage keys in frontend: Frontend code is client-side, so any keys you include will be visible to users. Always keep keys in backend environment variables.
  • Limit SAS permissions: Only grant the permissions you need (e.g., r for read-only if you just need to view the document). Avoid overprivileged access.
  • Shorten SAS expiration: Set a reasonable expiration time (1 hour or less is ideal) to minimize the risk of stolen SAS URLs being abused.
  • CORS configuration: Ensure your storage account and backend allow requests from your frontend domain. For Azure Blob Storage, configure CORS rules in the Azure Portal to permit your frontend origin.
  • Validate input: In the backend, validate that the document name is valid (e.g., no path traversal attempts) before generating the SAS URL.

If you’re using a different storage provider (like AWS S3), the core idea stays the same: use a backend to generate pre-signed URLs instead of doing it client-side.

内容的提问来源于stack exchange,提问作者vaibhav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:42:59