基于Express与Angular 5实现可选登录及API接口应用内访问权限控制
Great question! Let’s break down how to implement both the optional login functionality and restrict your API routes to only accept requests from your Angular app.
1. Implementing Optional Login for Enhanced Features
The goal here is to let unauthenticated users access basic functionality, while logged-in users get extra perks. Here’s how to set this up on both backend and frontend:
Backend (Express)
Create an optional authentication middleware that checks for a valid token but doesn’t block requests if none exists. This lets you attach user data to the request when available, then adjust responses accordingly.
const jwt = require('jsonwebtoken'); // Optional auth middleware const optionalAuth = (req, res, next) => { const authHeader = req.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.split(' ')[1]; try { // Verify token and attach user to request const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; } catch (err) { // Ignore invalid tokens - we're not enforcing auth here } } next(); }; // Use the middleware on routes that support optional login app.get('/api/content', optionalAuth, (req, res) => { let response = { basicContent: 'This is visible to everyone' }; // Add enhanced content if user is logged in if (req.user) { response.enhancedContent = `Welcome back, ${req.user.username}! Here's your exclusive content.`; } res.json(response); });
Frontend (Angular 5)
In your Angular service, check if a user token exists in local storage, and attach it to requests only when available. Update your UI to show/hide enhanced features based on login status.
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ContentService { constructor(private http: HttpClient) {} getContent() { let headers = new HttpHeaders(); const token = localStorage.getItem('authToken'); // Attach token if user is logged in if (token) { headers = headers.set('Authorization', `Bearer ${token}`); } return this.http.get('https://api.sample.com/api/content', { headers }); } }
2. Restricting API Routes to Internal App Access
Completely blocking tools like Postman is tricky (since headers can be forged), but combining these methods will effectively prevent most external requests:
Method 1: CSRF Protection (Recommended)
Angular automatically handles CSRF tokens, and Express can validate them to ensure requests come from your app.
Backend Setup
const cookieParser = require('cookie-parser'); const csurf = require('csurf'); const cors = require('cors'); // Configure CORS to allow your Angular app domain only app.use(cors({ origin: 'https://your-angular-app-domain.com', credentials: true })); // Parse cookies first (required for csurf) app.use(cookieParser()); // Enable CSRF protection via cookies app.use(csurf({ cookie: { httpOnly: true, sameSite: 'strict', secure: process.env.NODE_ENV === 'production' // Use HTTPS in production } })); // Endpoint to fetch CSRF token (Angular will use this automatically) app.get('/api/csrf-token', (req, res) => { res.json({ csrfToken: req.csrfToken() }); }); // Protect your internal routes - csurf will validate the token automatically app.get('/api/internal-only', (req, res) => { res.json({ data: 'This route is only accessible from your Angular app' }); });
Frontend Setup
Angular’s HttpClient automatically reads the XSRF-TOKEN cookie and sends it as the X-XSRF-TOKEN header in requests. No extra code needed here—just ensure your requests use HttpClient and have withCredentials enabled if cross-domain.
Method 2: Validate Request Origin/Referer
Add a middleware to check that requests come from your Angular app’s domain. This adds an extra layer of protection alongside CSRF.
const validateInternalOrigin = (req, res, next) => { const allowedOrigins = ['https://your-angular-app-domain.com']; const origin = req.headers.origin || req.headers.referer; // Block requests without a valid origin/referer if (!origin || !allowedOrigins.some(allowed => origin.startsWith(allowed))) { return res.status(403).json({ error: 'Forbidden: External requests are not allowed' }); } next(); }; // Apply to internal routes app.get('/api/internal-only', validateInternalOrigin, (req, res) => { res.json({ data: 'Internal-only content' }); });
Key Notes
- Optional Login: The middleware lets you gracefully handle both authenticated and unauthenticated users without blocking access.
- API Restriction: Combining CSRF and origin checks makes it extremely difficult for external tools to mimic valid requests from your app. While technically possible to forge headers, this setup covers most real-world scenarios.
内容的提问来源于stack exchange,提问作者Ibrahim Mohammed

