· Nacho Coll · Guides · 9 min lugemist
IPFS üleslaadimise tokenid: turvalised kliendipoolsed üleslaadimised ilma API võtmete paljastamiseta
Õppige, kuidas allkirjastatud üleslaadimise tokenid võimaldavad teil turvaliselt IPFS-i üles laadida brauseritest ja mobiilirakendustest ilma oma API võtit paljastamata.

Kaasaegsete veebirakenduste ehitamine nõuab sageli failide üleslaadimist otse kasutajate brauseritest pilvsalvestusse. Siiski seisavad arendajad IPFS üleslaadimise turvalisuse osas silmitsi keerulise dilemmaga: kuidas lubada kliendipoolseid üleslaadimisi ilma oma väärtuslikke API võtmeid potentsiaalsele väärkasutusele paljastamata?
Enamik IPFS kinnitamisteenuseid sunnivad teid ebamugavale valikule: kas käsitleda kõiki üleslaadimisi serveripoolselt (luues pudelikaelu ja keerukust) või manustada oma API võti kliendikoodisse (turvanõukogu). IPFS.NINJA lahendab selle ainulaadse funktsiooniga, mida ükski teine kinnitamisteenus ei paku: allkirjastatud üleslaadimise tokenid.

Probleem traditsiooniliste IPFS API võtmetega
Kliendipoolsete rakenduste ehitamisel, mis vajavad IPFS-i üleslaadimist, seisavad arendajad tavaliselt silmitsi mitme turvaprobleemiga:
API võtme paljastamise risk
API võtmete otse brauseri JavaScripti manustamine tähendab, et igaüks saab teie lähtekoodi vaadata ja teie mandaadid välja tõmmata. See võib kaasa tuua:
- Volitamata üleslaadimised, mis tarbivad teie salvestusmahtu
- Teie kinnitamisteenuse konto potentsiaalne väärkasutus
- Turvanõuete rikkumised ettevõtte keskkondades
Serveripoolsed pudelikaelad
Alternatiiv — kõigi üleslaadimiste suunamine läbi teie tagasüsteemi — tekitab mitmeid probleeme:
- Suurenenud serveri ribalaiuse kulud
- Kõrgem latentsus kasutajate jaoks
- Keerukamad infrastruktuuri nõuded
- Potentsiaalsed üksikud tõrkepunktid
Mobiilirakenduste turvalisus
Mobiilirakendused seisavad silmitsi sarnaste väljakutsetega, kus rakenduspakettidesse salvestatud API võtmeid saab pöördprojekteerimise teel välja tõmmata.
IPFS üleslaadimise tokenite tutvustamine
IPFS.NINJA allkirjastatud üleslaadimise tokenid pakuvad turvalist keskteed. Nii need töötavad:
- Server genereerib tokeni: teie tagasüsteem loob ajaliselt piiratud, allkirjastatud tokeni, kasutades teie API võtit
- Klient saab tokeni: token edastatakse turvaliselt teie esirakendusele
- Otsene üleslaadimine: kliendid laadivad otse IPFS.NINJA-sse, kasutades allkirjastatud tokenit
- Automaatne aegumine: tokenid aeguvad pärast määratud kestust, piirates paljastuse akent
See lähenemine ühendab serveripoolse autentimise turvalisuse kliendi otseüleslaadimise jõudluseeliste.
Üleslaadimise tokeni turvalisuse mõistmine
Allkirjastatud üleslaadimise tokenid kasutavad krüptograafilisi allkirju autentsuse tagamiseks ilma teie peamist API võtit paljastamata. Iga token sisaldab:
- Aegumise ajatempel: automaatne kehtetuks muutumine pärast määratud kestust
- Kasutuspiirangud: valikulised piirangud failide arvule või kogumahtule
- Krüptograafiline allkiri: takistab rikkumist või võltsimist
- Väljaandja kontroll: seostub tagasi teie autenditud kontoga
Erinevalt API võtmetest on üleslaadimise tokenid loodud turvaliseks manustamiseks kliendipoolsesse koodi. Isegi kui need välja tõmmatakse, pakuvad need piiratud juurdepääsu, mis automaatselt aegub.
Tagasüsteemi teostus: Express.js näide
Ehitame täieliku näite, mis näitab, kuidas teostada turvalisi kliendipoolseid IPFS üleslaadimisi. Esiteks, siin on Express.js tagasüsteem, mis genereerib üleslaadimise tokeneid:
// 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 {
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');
});Esirakenduse teostus: turvaline kliendi üleslaadimine
Nüüd, siin on esirakenduse kood, mis laadib faile turvaliselt üles, kasutades allkirjastatud tokenit:
<!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 s = document.getElementById('status'); s.className = `status ${type}`; s.textContent = message; }
displayResults(results) {
document.getElementById('results').innerHTML = '<h3>Upload Results:</h3>' + results.map(r => `<div class="status ${r.success ? 'success' : 'error'}" style="margin:10px 0;"><strong>${r.filename}</strong><br>${r.success ? `✅ CID: ${r.cid}<br>📊 Size: ${r.size} MB<br>🔗 URL: <a href="${r.httpUrl}" target="_blank">${r.httpUrl}</a>` : `❌ Error: ${r.error}`}</div>`).join('');
}
clearResults() { document.getElementById('results').innerHTML = ''; }
}
const uploader = new SecureIPFSUploader();
</script>
</body>
</html>Täiendavad turvakaalutlused
IPFS üleslaadimise turvalisuse teostamisel allkirjastatud tokenitega kaaluge neid lisameetmeid:
Tokeni ulatuse piirangud
Seadistage tokenid asjakohaste piirangutega:
// 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', maxUploads: 5, maxSizeMB: 10,
allowedMimeTypes: ['image/jpeg', 'image/png'],
ipWhitelist: ['192.168.1.0/24']
})
});Sisu valideerimine
Valideerige alati üleslaaditud sisu oma tagasüsteemis:
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' }); }
});Kiirusepiirang
Rakendage oma tokeni genereerimise lõpp-punktile täiendav kiirusepiirang:
const rateLimit = require('express-rate-limit');
const tokenLimiter = rateLimit({
windowMs: 15 * 60 * 1000, max: 10,
message: 'Too many token requests, please try again later'
});
app.use('/api/generate-upload-token', tokenLimiter);Eelised traditsiooniliste lähenemisviiside ees
Allkirjastatud üleslaadimise tokenid pakuvad mitmeid eeliseid alternatiivsete IPFS üleslaadimise turvameetodite ees:
vs. serveripoolne proksimine
- Jõudlus: otseüleslaadimised kõrvaldavad serveri ribalaiuse kasutamise
- Skaleeritavus: serveripoolsed pudelikaelad puuduvad kõrge üleslaadimise perioodidel
- Kulu: vähenenud ribalaiuse ja töötlemise kulud
- Kasutajakogemus: parem üleslaadimiskiirus ja edenemise jälgimine
vs. kliendipoolne API võti
- Turvalisus: API võtme väljavõtmise või väärkasutuse risk puudub
- Vastavus: vastab turvaauditi nõuetele
- Juurdepääsukontroll: peeneteralisne õiguste haldus ja automaatne aegumine
- Jälgimine: parem üleslaadimisallikate ja -mustrite jälgimine
vs. teised kinnitamisteenused
IPFS.NINJA on praegu ainus suurem kinnitamisteenus, mis pakub allkirjastatud üleslaadimise tokeneid. Konkurendid nagu Pinata nõuavad kas serveripoolset proksimist või kliendipoolse API võtme paljastamist, muutes selle ainulaadseks eristajaks.
Lisateabe saamiseks IPFS.NINJA võrdluse kohta teiste teenustega vaadake meie põhjalikku võrdlusjuhendit.
Tootmisse juurutamise näpunäited
Allkirjastatud üleslaadimise tokenite tootmisse juurutamisel:
Keskkonna seadistamine
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']
};Jälgimine ja logimine
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
});Vigade käsitlemine
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.' });
});Integratsioon populaarsete raamistikega
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 };
}Kokkuvõte
Allkirjastatud üleslaadimise tokenid lahendavad kriitilise turvaprobleemi detsentraliseeritud rakenduste arendamisel. Pakkudes turvalist viisi kliendipoolsete otseüleslaadimiste lubamiseks IPFS-i ilma API võtmete paljastamiseta, avavad need uusi arhitektuurseid võimalusi kaasaegsetele veebirakendustele.
Olenemata sellest, kas ehitate sisuhaldussüsteemi, NFT turgu või mis tahes rakendust, mis nõuab turvalisi failide üleslaadimisi, pakuvad IPFS.NINJA üleslaadimise tokenid teile vajalikku turvalisust ja paindlikkust. Teostus on lihtne, turvaeelised on märkimisväärsed ja jõudluse parandused on olulised.
IPFS põhitõdede kohta lisateabe saamiseks vaadake meie juhendit mis on IPFS kinnitamine või uurige meie täielikku API õpetust. Erinevaid valikuid hindavate arendajate jaoks pakub meie parimate IPFS kinnitamisteenuste võrdlus põhjalikke ülevaateid.
Valmis kinnitamist alustama? Looge tasuta konto --- 500 faili, 1 GB salvestusruum, spetsiaalne gateway. Krediitkaarti pole vaja.
