如何在基于类组件的Create React App中集成Passport.js?
Got it, let's walk through how to integrate Passport.js with your Create React App that uses class components. Since Passport is a backend authentication library, we’ll split this into two main parts: setting up the backend (with Express, since that’s common with Passport) and hooking up your React class components to it.
Backend Setup (Express + Passport)
First, you’ll need to configure Passport on your backend—this is where the authentication logic lives. Using the ADFS example you referenced, here’s a simplified setup:
Install dependencies:
npm install express passport passport-saml cors express-sessionConfigure Passport and your server:
const express = require('express'); const passport = require('passport'); const SamlStrategy = require('passport-saml').Strategy; const cors = require('cors'); const session = require('express-session'); // Initialize app const app = express(); // CORS setup (allow your React app to communicate with the backend) app.use(cors({ origin: 'http://localhost:3000', // Your React app URL credentials: true // Critical for passing session cookies })); // Session setup (required to persist login state) app.use(session({ secret: 'your-strong-secret-key', resave: false, saveUninitialized: false })); // Initialize Passport app.use(passport.initialize()); app.use(passport.session()); // Configure ADFS SAML Strategy passport.use(new SamlStrategy({ entryPoint: 'https://your-adfs-server/adfs/ls/', issuer: 'your-app-issuer-id', callbackURL: 'http://localhost:3001/auth/adfs/callback', // Add other required config (like certs) from your ADFS setup }, (profile, done) => { // Handle user lookup/creation here (e.g., check your database) // For simplicity, we'll just pass the profile through return done(null, profile); })); // Serialize/deserialize user for session storage passport.serializeUser((user, done) => done(null, user)); passport.deserializeUser((user, done) => done(null, user)); // Auth routes // Trigger ADFS login app.get('/auth/adfs', passport.authenticate('saml')); // ADFS callback route app.get('/auth/adfs/callback', passport.authenticate('saml', { failureRedirect: '/login' }), (req, res) => { // Redirect back to your React app after successful login res.redirect('http://localhost:3000/dashboard'); } ); // Endpoint to get current user info app.get('/api/user', (req, res) => { if (req.user) { res.json(req.user); } else { res.status(401).json({ message: 'Not authenticated' }); } }); app.listen(3001, () => console.log('Backend running on port 3001'));
React Class Component Integration
Now let’s connect your React class components to this backend. We’ll cover login triggers, checking auth state, and protecting routes.
1. Login Page Component
Create a login component that redirects users to the Passport auth endpoint:
import React from 'react'; class LoginPage extends React.Component { handleADFSLogin = () => { // Redirect to your backend's Passport login route window.location.href = 'http://localhost:3001/auth/adfs'; }; render() { return ( <div className="login-container"> <h1>Welcome to Our App</h1> <button onClick={this.handleADFSLogin} className="login-btn"> Login with ADFS </button> </div> ); } } export default LoginPage;
2. Protected Dashboard Component
Create a dashboard component that checks if the user is authenticated on mount:
import React from 'react'; class Dashboard extends React.Component { state = { user: null, loading: true, error: null }; componentDidMount() { this.fetchCurrentUser(); } fetchCurrentUser = async () => { try { const response = await fetch('http://localhost:3001/api/user', { credentials: 'include' // Critical: sends session cookies to backend }); if (response.ok) { const user = await response.json(); this.setState({ user, loading: false }); } else { // User isn't authenticated—redirect to login this.props.history.push('/login'); } } catch (err) { this.setState({ error: err.message, loading: false }); } }; render() { const { user, loading, error } = this.state; if (loading) return <div>Loading user info...</div>; if (error) return <div>Error: {error}</div>; return ( <div className="dashboard"> <h1>Welcome, {user.displayName}!</h1> <p>Your email: {user.email}</p> {/* Add other user-specific content here */} </div> ); } } export default Dashboard;
3. Protected Route Higher-Order Component (HOC)
To reuse auth checks across multiple components, create an HOC that wraps protected routes:
import React from 'react'; import { Redirect } from 'react-router-dom'; const requireAuth = (WrappedComponent) => { return class extends React.Component { state = { isAuthenticated: false, loading: true }; componentDidMount() { this.checkAuthStatus(); } checkAuthStatus = async () => { try { const response = await fetch('http://localhost:3001/api/user', { credentials: 'include' }); this.setState({ isAuthenticated: response.ok, loading: false }); } catch (err) { this.setState({ isAuthenticated: false, loading: false }); } }; render() { const { isAuthenticated, loading } = this.state; if (loading) return <div>Checking auth...</div>; return isAuthenticated ? ( <WrappedComponent {...this.props} /> ) : ( <Redirect to="/login" /> ); } }; }; export default requireAuth;
Then use it to wrap your protected components in your router setup:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import LoginPage from './LoginPage'; import Dashboard from './Dashboard'; import requireAuth from './requireAuth'; function App() { return ( <Router> <Switch> <Route path="/login" component={LoginPage} /> <Route path="/dashboard" component={requireAuth(Dashboard)} /> <Route path="/" exact component={LoginPage} /> </Switch> </Router> ); } export default App;
Key Notes & Troubleshooting
- CORS & Credentials: Make sure your backend’s CORS config includes
credentials: trueand your React fetch requests includecredentials: 'include'—this is how session cookies are passed between frontend and backend. - Session Persistence: If users are logged out on page refresh, double-check your backend session config (ensure the secret is set and session middleware is correctly ordered).
- ADFS Config: Verify your ADFS strategy settings (entryPoint, issuer, callbackURL) match what’s configured on your ADFS server—mismatches here will cause authentication failures.
内容的提问来源于stack exchange,提问作者user25010

