· Nacho Coll · Guides · 11 मिनट पढ़ें
IPFS अपलोड टोकन: API कुंजी उजागर किए बिना सुरक्षित क्लाइंट-साइड अपलोड
जानें कि कैसे हस्ताक्षरित अपलोड टोकन आपको API कुंजी उजागर किए बिना ब्राउज़र और मोबाइल ऐप्स से सुरक्षित रूप से IPFS पर अपलोड करने देते हैं।

आधुनिक वेब एप्लिकेशन बनाते समय अक्सर उपयोगकर्ताओं के ब्राउज़र से सीधे क्लाउड स्टोरेज में फ़ाइलें अपलोड करने की आवश्यकता होती है। हालांकि, IPFS अपलोड सुरक्षा के मामले में, डेवलपर्स एक चुनौतीपूर्ण दुविधा का सामना करते हैं: अपनी कीमती API कुंजी को उजागर किए बिना क्लाइंट-साइड अपलोड कैसे अनुमति दें?
अधिकांश IPFS पिनिंग सेवाएं आपको एक असुविधाजनक विकल्प देती हैं: या तो सभी अपलोड सर्वर-साइड पर संभालें (बाधाएं और जटिलता पैदा करते हुए) या अपनी API कुंजी क्लाइंट कोड में एम्बेड करें (एक सुरक्षा दुःस्वप्न)। IPFS.NINJA इसे एक अनूठी सुविधा से हल करता है जो किसी अन्य पिनिंग सेवा में नहीं है: हस्ताक्षरित अपलोड टोकन।

पारंपरिक IPFS API कुंजियों की समस्या
IPFS पर अपलोड करने की आवश्यकता वाले क्लाइंट-साइड एप्लिकेशन बनाते समय, डेवलपर्स आमतौर पर कई सुरक्षा चुनौतियों का सामना करते हैं:
API कुंजी उजागर होने का जोखिम
ब्राउज़र JavaScript में सीधे API कुंजियां एम्बेड करने का मतलब है कि कोई भी आपका सोर्स कोड देख सकता है और आपकी क्रेडेंशियल्स निकाल सकता है। इससे हो सकता है:
- अनधिकृत अपलोड आपके स्टोरेज कोटे का उपभोग कर रहे हैं
- आपके पिनिंग सेवा खाते का संभावित दुरुपयोग
- एंटरप्राइज़ वातावरण में सुरक्षा अनुपालन उल्लंघन
सर्वर-साइड बाधाएं
विकल्प — सभी अपलोड को अपने बैकएंड के माध्यम से रूट करना — कई समस्याएं पैदा करता है:
- सर्वर बैंडविड्थ लागत में वृद्धि
- उपयोगकर्ताओं के लिए अधिक विलंबता
- अधिक जटिल बुनियादी ढांचा आवश्यकताएं
- संभावित एकल विफलता बिंदु
मोबाइल ऐप सुरक्षा
मोबाइल एप्लिकेशन भी इसी तरह की चुनौतियों का सामना करते हैं, जहां ऐप बंडलों में संग्रहीत API कुंजियों को रिवर्स इंजीनियरिंग के माध्यम से निकाला जा सकता है।
IPFS अपलोड टोकन का परिचय
IPFS.NINJA के हस्ताक्षरित अपलोड टोकन एक सुरक्षित मध्य मार्ग प्रदान करते हैं। यह इस प्रकार काम करता है:
- सर्वर टोकन जेनरेट करता है: आपका बैकएंड आपकी API कुंजी का उपयोग करके एक समय-सीमित, हस्ताक्षरित टोकन बनाता है
- क्लाइंट टोकन प्राप्त करता है: टोकन सुरक्षित रूप से आपके फ्रंटएंड एप्लिकेशन को प्रेषित किया जाता है
- सीधा अपलोड: क्लाइंट हस्ताक्षरित टोकन का उपयोग करके सीधे IPFS.NINJA पर अपलोड करते हैं
- स्वचालित समाप्ति: टोकन एक निर्धारित अवधि के बाद समाप्त हो जाते हैं, जिससे एक्सपोज़र विंडो सीमित होती है
यह दृष्टिकोण सर्वर-साइड प्रमाणीकरण की सुरक्षा को सीधे क्लाइंट अपलोड के प्रदर्शन लाभों के साथ जोड़ता है।
अपलोड टोकन सुरक्षा को समझना
हस्ताक्षरित अपलोड टोकन आपकी मुख्य API कुंजी को उजागर किए बिना प्रामाणिकता सुनिश्चित करने के लिए क्रिप्टोग्राफ़िक हस्ताक्षरों का उपयोग करते हैं। प्रत्येक टोकन में शामिल है:
- समाप्ति टाइमस्टैम्प: निर्दिष्ट अवधि के बाद स्वचालित अमान्यकरण
- उपयोग सीमाएं: फ़ाइल संख्या या कुल आकार पर वैकल्पिक सीमाएं
- क्रिप्टोग्राफ़िक हस्ताक्षर: छेड़छाड़ या जालसाज़ी को रोकता है
- जारीकर्ता सत्यापन: आपके प्रमाणित खाते से वापस लिंक करता है
API कुंजियों के विपरीत, अपलोड टोकन क्लाइंट-साइड कोड में सुरक्षित रूप से एम्बेड करने के लिए डिज़ाइन किए गए हैं। निकाले जाने पर भी, वे सीमित पहुंच प्रदान करते हैं जो स्वचालित रूप से समाप्त हो जाती है।
बैकएंड कार्यान्वयन: Express.js उदाहरण
आइए एक पूर्ण उदाहरण बनाएं जो दिखाता है कि सुरक्षित क्लाइंट-साइड IPFS अपलोड कैसे लागू करें। सबसे पहले, यह अपलोड टोकन जेनरेट करने वाला Express.js बैकएंड है:
// server.js
const express = require('express');
const cors = require('cors');
const app = express();
app.use(express.json());
app.use(cors());
// Your IPFS.NINJA API key (keep this secure on server-side only)
const IPFS_API_KEY = 'bws_1234567890abcdef1234567890abcdef12345678';
// Generate a signed upload token
app.post('/api/generate-upload-token', async (req, res) => {
try {
const response = await fetch('https://api.ipfs.ninja/upload-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': IPFS_API_KEY
},
body: JSON.stringify({
expiresIn: '1h', // Token valid for 1 hour
maxUploads: 10, // Optional: limit number of uploads
maxSizeMB: 50 // Optional: limit total upload size
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const tokenData = await response.json();
res.json({
success: true,
uploadToken: tokenData.token,
expiresAt: tokenData.expiresAt
});
} catch (error) {
console.error('Token generation failed:', error);
res.status(500).json({
success: false,
error: 'Failed to generate upload token'
});
}
});
// Optional: Endpoint to verify uploads completed successfully
app.post('/api/verify-upload', async (req, res) => {
const { cid } = req.body;
try {
// Verify the file was pinned successfully
const response = await fetch(`https://api.ipfs.ninja/pins/${cid}`, {
headers: {
'X-Api-Key': IPFS_API_KEY
}
});
const pinData = await response.json();
res.json({
success: true,
verified: pinData.pinned,
metadata: pinData
});
} catch (error) {
res.status(500).json({
success: false,
error: 'Verification failed'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});फ्रंटएंड कार्यान्वयन: सुरक्षित क्लाइंट अपलोड
अब, यह हस्ताक्षरित टोकन का उपयोग करके सुरक्षित रूप से फ़ाइलें अपलोड करने वाला फ्रंटएंड कोड है:
<!DOCTYPE html>
<html>
<head>
<title>Secure IPFS Upload Demo</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
.upload-area { border: 2px dashed #ccc; padding: 20px; text-align: center; margin: 20px 0; }
.upload-area.dragover { border-color: #007cba; background: #f0f8ff; }
button { background: #007cba; color: white; border: none; padding: 10px 20px; cursor: pointer; }
.status { margin: 10px 0; padding: 10px; border-radius: 4px; }
.success { background: #d4edda; color: #155724; }
.error { background: #f8d7da; color: #721c24; }
.info { background: #d1ecf1; color: #0c5460; }
</style>
</head>
<body>
<h1>Secure IPFS Upload with Signed Tokens</h1>
<div class="upload-area" id="uploadArea">
<p>Drag & drop files here or click to select</p>
<input type="file" id="fileInput" multiple style="display: none;">
<button onclick="document.getElementById('fileInput').click()">Select Files</button>
</div>
<div id="status"></div>
<div id="results"></div>
<script>
class SecureIPFSUploader {
constructor() {
this.uploadToken = null;
this.tokenExpiry = null;
this.setupEventListeners();
}
setupEventListeners() {
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
this.handleFiles(Array.from(e.dataTransfer.files));
});
fileInput.addEventListener('change', (e) => {
this.handleFiles(Array.from(e.target.files));
});
}
async getUploadToken() {
if (this.uploadToken && this.tokenExpiry && new Date() < new Date(this.tokenExpiry)) {
return this.uploadToken;
}
try {
this.showStatus('Generating secure upload token...', 'info');
const response = await fetch('/api/generate-upload-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) throw new Error(`Failed to generate token: ${response.statusText}`);
const data = await response.json();
if (!data.success) throw new Error(data.error || 'Token generation failed');
this.uploadToken = data.uploadToken;
this.tokenExpiry = data.expiresAt;
return this.uploadToken;
} catch (error) {
this.showStatus(`Token generation failed: ${error.message}`, 'error');
throw error;
}
}
async uploadFile(file) {
try {
const token = await this.getUploadToken();
const fileBase64 = await this.fileToBase64(file);
this.showStatus(`Uploading ${file.name} to IPFS...`, 'info');
const response = await fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Signed ${token}`
},
body: JSON.stringify({
content: fileBase64,
description: `File uploaded via secure token: ${file.name}`,
metadata: {
filename: file.name,
fileType: file.type,
uploadedAt: new Date().toISOString(),
uploadMethod: 'signed-token'
}
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Upload failed: ${response.status} ${errorText}`);
}
const result = await response.json();
return {
success: true, filename: file.name, cid: result.cid,
size: result.sizeMB, ipfsUri: result.uris.ipfs, httpUrl: result.uris.url
};
} catch (error) {
return { success: false, filename: file.name, error: error.message };
}
}
async handleFiles(files) {
if (files.length === 0) return;
this.clearResults();
try {
const results = await Promise.all(files.map(file => this.uploadFile(file)));
this.displayResults(results);
const successful = results.filter(r => r.success).length;
if (successful === results.length) {
this.showStatus(`✅ Successfully uploaded ${successful} file(s) to IPFS!`, 'success');
} else {
this.showStatus(`⚠️ Uploaded ${successful}/${results.length} files. Check results below.`, 'error');
}
} catch (error) {
this.showStatus(`Upload failed: ${error.message}`, 'error');
}
}
fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.split(',')[1]);
reader.onerror = error => reject(error);
});
}
showStatus(message, type) {
const statusDiv = document.getElementById('status');
statusDiv.className = `status ${type}`;
statusDiv.textContent = message;
}
displayResults(results) {
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '<h3>Upload Results:</h3>' +
results.map(result => `
<div class="status ${result.success ? 'success' : 'error'}" style="margin: 10px 0;">
<strong>${result.filename}</strong><br>
${result.success ?
`✅ CID: ${result.cid}<br>📊 Size: ${result.size} MB<br>🔗 URL: <a href="${result.httpUrl}" target="_blank">${result.httpUrl}</a>` :
`❌ Error: ${result.error}`}
</div>`).join('');
}
clearResults() { document.getElementById('results').innerHTML = ''; }
}
const uploader = new SecureIPFSUploader();
</script>
</body>
</html>उन्नत सुरक्षा विचार
हस्ताक्षरित टोकन के साथ IPFS अपलोड सुरक्षा लागू करते समय, इन अतिरिक्त सुरक्षा उपायों पर विचार करें:
टोकन स्कोप सीमाएं
उचित प्रतिबंधों के साथ टोकन कॉन्फ़िगर करें:
// Generate token with specific constraints
const restrictedToken = await fetch('https://api.ipfs.ninja/upload-tokens', {
method: 'POST',
headers: {
'X-Api-Key': IPFS_API_KEY
},
body: JSON.stringify({
expiresIn: '30m', // Short expiration
maxUploads: 5, // Limited upload count
maxSizeMB: 10, // Size restriction
allowedMimeTypes: ['image/jpeg', 'image/png'], // File type restrictions
ipWhitelist: ['192.168.1.0/24'] // IP-based access control
})
});सामग्री सत्यापन
हमेशा अपने बैकएंड पर अपलोड की गई सामग्री का सत्यापन करें:
app.post('/api/validate-upload', async (req, res) => {
const { cid } = req.body;
try {
const response = await fetch(`https://ipfs.ninja/ipfs/${cid}`);
const contentType = response.headers.get('content-type');
if (!isValidContentType(contentType)) {
await deleteFromIPFS(cid);
return res.status(400).json({ error: 'Invalid content type' });
}
res.json({ success: true, validated: true });
} catch (error) {
res.status(500).json({ error: 'Validation failed' });
}
});दर सीमा
अपने टोकन जनरेशन एंडपॉइंट पर अतिरिक्त दर सीमा लागू करें:
const rateLimit = require('express-rate-limit');
const tokenLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // Limit each IP to 10 token requests per windowMs
message: 'Too many token requests, please try again later'
});
app.use('/api/generate-upload-token', tokenLimiter);पारंपरिक दृष्टिकोणों पर लाभ
हस्ताक्षरित अपलोड टोकन वैकल्पिक IPFS अपलोड सुरक्षा विधियों पर कई लाभ प्रदान करते हैं:
सर्वर-साइड प्रॉक्सी की तुलना में
- प्रदर्शन: सीधे अपलोड सर्वर बैंडविड्थ उपयोग को समाप्त करते हैं
- स्केलेबिलिटी: उच्च अपलोड अवधि के दौरान कोई सर्वर बाधा नहीं
- लागत: कम बैंडविड्थ और प्रोसेसिंग लागत
- उपयोगकर्ता अनुभव: तेज अपलोड गति और प्रगति ट्रैकिंग
क्लाइंट-साइड API कुंजियों की तुलना में
- सुरक्षा: API कुंजी निष्कर्षण या दुरुपयोग का कोई जोखिम नहीं
- अनुपालन: सुरक्षा ऑडिट आवश्यकताओं को पूरा करता है
- पहुंच नियंत्रण: बारीक अनुमतियां और स्वचालित समाप्ति
- निगरानी: अपलोड स्रोतों और पैटर्न की बेहतर ट्रैकिंग
अन्य पिनिंग सेवाओं की तुलना में
IPFS.NINJA वर्तमान में हस्ताक्षरित अपलोड टोकन प्रदान करने वाली एकमात्र प्रमुख पिनिंग सेवा है। Pinata जैसे प्रतिस्पर्धियों को सर्वर-साइड प्रॉक्सी या क्लाइंट-साइड API कुंजी एक्सपोज़र की आवश्यकता होती है, जिससे यह एक अनूठा अंतर बनता है।
IPFS.NINJA की अन्य सेवाओं से तुलना के बारे में अधिक जानकारी के लिए, हमारी व्यापक तुलना गाइड देखें।
प्रोडक्शन परिनियोजन सुझाव
प्रोडक्शन में हस्ताक्षरित अपलोड टोकन परिनियोजित करते समय:
पर्यावरण कॉन्फ़िगरेशन
संवेदनशील कॉन्फ़िगरेशन को सुरक्षित रूप से संग्रहीत करें:
// Use environment variables for production
const config = {
ipfsApiKey: process.env.IPFS_API_KEY,
tokenExpiry: process.env.UPLOAD_TOKEN_EXPIRY || '1h',
maxFileSize: process.env.MAX_FILE_SIZE_MB || 50,
allowedOrigins: process.env.ALLOWED_ORIGINS?.split(',') || ['localhost:3000']
};निगरानी और लॉगिंग
सुरक्षा निगरानी के लिए व्यापक लॉगिंग लागू करें:
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'upload-security.log' })
]
});
logger.info('Upload token generated', {
userId: req.user.id,
clientIP: req.ip,
userAgent: req.get('User-Agent'),
expiresAt: tokenData.expiresAt
});त्रुटि संचालन
मजबूत त्रुटि संचालन लागू करें जो संवेदनशील जानकारी लीक न करे:
app.use((error, req, res, next) => {
logger.error('Upload token error', {
error: error.message,
stack: error.stack,
userId: req.user?.id,
endpoint: req.path
});
res.status(500).json({
success: false,
error: 'An internal error occurred. Please try again.'
});
});लोकप्रिय फ्रेमवर्क के साथ एकीकरण
हस्ताक्षरित अपलोड टोकन आधुनिक वेब फ्रेमवर्क के साथ सहजता से एकीकृत होते हैं। यहां त्वरित एकीकरण उदाहरण हैं:
React Hook
import { useState, useCallback } from 'react';
export function useSecureIPFSUpload() {
const [uploading, setUploading] = useState(false);
const [uploadToken, setUploadToken] = useState(null);
const getToken = useCallback(async () => {
if (uploadToken?.expiresAt && new Date() < new Date(uploadToken.expiresAt)) {
return uploadToken.token;
}
const response = await fetch('/api/generate-upload-token', { method: 'POST' });
const data = await response.json();
setUploadToken(data);
return data.uploadToken;
}, [uploadToken]);
const uploadFile = useCallback(async (file) => {
setUploading(true);
try {
const token = await getToken();
// Upload logic here...
} finally {
setUploading(false);
}
}, [getToken]);
return { uploadFile, uploading };
}Vue.js Composable
import { ref } from 'vue';
export function useSecureUpload() {
const uploading = ref(false);
const uploadProgress = ref(0);
const uploadFile = async (file) => {
uploading.value = true;
// Implementation here...
};
return {
uploading: readonly(uploading),
uploadProgress: readonly(uploadProgress),
uploadFile
};
}निष्कर्ष
हस्ताक्षरित अपलोड टोकन विकेंद्रीकृत एप्लिकेशन विकास में एक महत्वपूर्ण सुरक्षा चुनौती को हल करते हैं। API कुंजी उजागर किए बिना IPFS पर सीधे क्लाइंट-साइड अपलोड सक्षम करने का एक सुरक्षित तरीका प्रदान करके, वे आधुनिक वेब एप्लिकेशन के लिए नई वास्तुकला संभावनाएं खोलते हैं।
चाहे आप सामग्री प्रबंधन प्रणाली, NFT मार्केटप्लेस, या सुरक्षित फ़ाइल अपलोड की आवश्यकता वाला कोई भी एप्लिकेशन बना रहे हों, IPFS.NINJA के अपलोड टोकन आपको आवश्यक सुरक्षा और लचीलापन प्रदान करते हैं। कार्यान्वयन सीधा है, सुरक्षा लाभ महत्वपूर्ण हैं, और प्रदर्शन सुधार पर्याप्त हैं।
IPFS की बुनियादी बातों के बारे में अधिक जानने के लिए, IPFS पिनिंग क्या है हमारी गाइड देखें या हमारा पूर्ण API ट्यूटोरियल एक्सप्लोर करें। विभिन्न विकल्पों का मूल्यांकन करने वाले डेवलपर्स के लिए, हमारी सर्वश्रेष्ठ IPFS पिनिंग सेवाओं की तुलना व्यापक अंतर्दृष्टि प्रदान करती है।
अपने एप्लिकेशन में सुरक्षित क्लाइंट-साइड IPFS अपलोड लागू करने के लिए तैयार हैं? आधुनिक सुरक्षा प्रथाओं और विकेंद्रीकृत स्टोरेज का संयोजन इस दृष्टिकोण को सुरक्षा मानकों को बनाए रखते हुए स्केल करने की आवश्यकता वाले प्रोडक्शन एप्लिकेशन के लिए आदर्श बनाता है।
पिनिंग शुरू करने के लिए तैयार हैं? मुफ्त खाता बनाएं — 500 फ़ाइलें, 1 GB स्टोरेज, समर्पित गेटवे। क्रेडिट कार्ड आवश्यक नहीं।
