You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Laravel多认证实现咨询:6类用户分双路由登录方案

Hey there! Let's walk through exactly how to build this multi-user login system, covering both the Laravel backend and React frontend. I'll break it down into clear, actionable steps so you can implement it easily.

Laravel Backend Implementation

First, we'll focus on securing the routes, separating login flows, and preventing cross-access between customer and admin users.

1. Configure Authentication Guards & Providers

We need two distinct guards to handle customer and admin authentication. Update your config/auth.php to define separate guards and model providers:

// config/auth.php
'guards' => [
    'customer' => [
        'driver' => 'session',
        'provider' => 'customers',
    ],
    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [
    'customers' => [
        'driver' => 'eloquent',
        'model' => App\Models\Customer::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class, // Use this model for all 5 admin types (add a `type` column to distinguish them)
    ],
],

2. Update Routes & Controllers

Split your login routes into GET (form display) and POST (login processing), then add route protection with custom middleware.

Updated Routes (web.php)

// Customer login flow
Route::get('/login', 'CustomerLoginController@showLoginForm')->name('customer.login');
Route::post('/login', 'CustomerLoginController@processLogin');

// Admin login flow
Route::get('/system/base-admin', 'AdminLoginController@showAdminLoginForm')->name('system.admin');
Route::post('/system/base-admin', 'AdminLoginController@processAdminLogin');

// Protected customer routes (only accessible to logged-in customers)
Route::middleware('auth.customer')->group(function () {
    Route::get('/customer/dashboard', 'CustomerDashboardController@index')->name('customer.dashboard');
    Route::post('/customer/logout', 'CustomerLoginController@logout')->name('customer.logout');
});

// Protected admin routes (only accessible to logged-in admins)
Route::middleware('auth.admin')->group(function () {
    Route::get('/system/admin/dashboard', 'AdminDashboardController@index')->name('admin.dashboard');
    Route::post('/system/admin/logout', 'AdminLoginController@logout')->name('admin.logout');
});

Customer Login Controller

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CustomerLoginController extends Controller
{
    public function showLoginForm()
    {
        // Redirect logged-in customers directly to their dashboard
        if (Auth::guard('customer')->check()) {
            return redirect()->route('customer.dashboard');
        }
        return view('customer.login');
    }

    public function processLogin(Request $request)
    {
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        if (Auth::guard('customer')->attempt($credentials)) {
            $request->session()->regenerate();
            return redirect()->intended('/customer/dashboard');
        }

        // Redirect back to customer login with error
        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ])->onlyInput('email');
    }

    public function logout(Request $request)
    {
        Auth::guard('customer')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect()->route('customer.login');
    }
}

Admin Login Controller

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Admin;

class AdminLoginController extends Controller
{
    public function showAdminLoginForm()
    {
        // Redirect logged-in admins directly to their dashboard
        if (Auth::guard('admin')->check()) {
            return redirect()->route('admin.dashboard');
        }
        return view('admin.login');
    }

    public function processAdminLogin(Request $request)
    {
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        // Validate the user is one of the 5 admin types
        $admin = Admin::where('email', $request->email)->first();
        if (!$admin || !in_array($admin->type, ['admin_type_1', 'admin_type_2', 'admin_type_3', 'admin_type_4', 'admin_type_5'])) {
            return back()->withErrors([
                'email' => 'Invalid admin credentials.',
            ])->onlyInput('email');
        }

        if (Auth::guard('admin')->attempt($credentials)) {
            $request->session()->regenerate();
            return redirect()->intended('/system/admin/dashboard');
        }

        // Redirect back to admin login with error
        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ])->onlyInput('email');
    }

    public function logout(Request $request)
    {
        Auth::guard('admin')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect()->route('system.admin');
    }
}

3. Custom Middleware for Route Protection

Create two middleware to prevent cross-access between customer and admin routes:

CheckCustomerGuard Middleware

// app/Http/Middleware/CheckCustomerGuard.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CheckCustomerGuard
{
    public function handle(Request $request, Closure $next)
    {
        // Block admins from accessing customer routes
        if (Auth::guard('admin')->check()) {
            return redirect()->route('admin.dashboard');
        }

        // Redirect unauthenticated users to customer login
        if (!Auth::guard('customer')->check()) {
            return redirect()->route('customer.login');
        }

        return $next($request);
    }
}

CheckAdminGuard Middleware

// app/Http/Middleware/CheckAdminGuard.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CheckAdminGuard
{
    public function handle(Request $request, Closure $next)
    {
        // Block customers from accessing admin routes
        if (Auth::guard('customer')->check()) {
            return redirect()->route('customer.dashboard');
        }

        // Redirect unauthenticated users to admin login
        if (!Auth::guard('admin')->check()) {
            return redirect()->route('system.admin');
        }

        return $next($request);
    }
}

Register these middleware in app/Http/Kernel.php:

protected $routeMiddleware = [
    // ...
    'auth.customer' => \App\Http\Middleware\CheckCustomerGuard::class,
    'auth.admin' => \App\Http\Middleware\CheckAdminGuard::class,
];

React Frontend Implementation

Now let's handle the frontend to match the backend flow, with separate login forms and route protection.

1. Separate Login Components

Create two distinct login components for customers and admins:

CustomerLogin.jsx

import { useState } from 'react';
import { useNavigate } from 'react-router-dom';

export default function CustomerLogin() {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const navigate = useNavigate();

    const handleSubmit = async (e) => {
        e.preventDefault();
        setError('');

        try {
            const response = await fetch('/login', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
                },
                body: JSON.stringify({ email, password })
            });

            if (!response.ok) {
                const data = await response.json();
                setError(data.email || 'Login failed');
                return;
            }

            navigate('/customer/dashboard');
        } catch (err) {
            setError('An error occurred during login');
        }
    };

    return (
        <div className="login-form">
            <h2>Customer Login</h2>
            {error && <p className="error">{error}</p>}
            <form onSubmit={handleSubmit}>
                <div>
                    <label>Email:</label>
                    <input
                        type="email"
                        value={email}
                        onChange={(e) => setEmail(e.target.value)}
                        required
                    />
                </div>
                <div>
                    <label>Password:</label>
                    <input
                        type="password"
                        value={password}
                        onChange={(e) => setPassword(e.target.value)}
                        required
                    />
                </div>
                <button type="submit">Login</button>
            </form>
        </div>
    );
}

AdminLogin.jsx

This is nearly identical to the customer login component, with changes to the form title, API endpoint, and redirect path:

// Replace the handleSubmit fetch URL with '/system/base-admin'
// Redirect to '/system/admin/dashboard' on success

2. Protected Route Components

Create components to guard routes and prevent cross-access:

ProtectedCustomerRoute.jsx

import { useEffect, useState } from 'react';
import { Navigate, Outlet } from 'react-router-dom';

export default function ProtectedCustomerRoute() {
    const [isAuthenticated, setIsAuthenticated] = useState(null);
    const [isAdmin, setIsAdmin] = useState(false);

    useEffect(() => {
        const checkAuth = async () => {
            // Check if user is logged in as customer
            const customerRes = await fetch('/api/customer/check-auth');
            if (customerRes.ok) {
                setIsAuthenticated(true);
                return;
            }

            // Check if user is logged in as admin
            const adminRes = await fetch('/api/admin/check-auth');
            if (adminRes.ok) {
                setIsAdmin(true);
            }
            setIsAuthenticated(false);
        };

        checkAuth();
    }, []);

    if (isAuthenticated === null) return <div>Loading...</div>;
    if (isAdmin) return <Navigate to="/system/admin/dashboard" replace />;
    return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
}

ProtectedAdminRoute.jsx

import { useEffect, useState } from 'react';
import { Navigate, Outlet } from 'react-router-dom';

export default function ProtectedAdminRoute() {
    const [isAuthenticated, setIsAuthenticated] = useState(null);
    const [isCustomer, setIsCustomer] = useState(false);

    useEffect(() => {
        const checkAuth = async () => {
            // Check if user is logged in as admin
            const adminRes = await fetch('/api/admin/check-auth');
            if (adminRes.ok) {
                setIsAuthenticated(true);
                return;
            }

            // Check if user is logged in as customer
            const customerRes = await fetch('/api/customer/check-auth');
            if (customerRes.ok) {
                setIsCustomer(true);
            }
            setIsAuthenticated(false);
        };

        checkAuth();
    }, []);

    if (isAuthenticated === null) return <div>Loading...</div>;
    if (isCustomer) return <Navigate to="/customer/dashboard" replace />;
    return isAuthenticated ? <Outlet /> : <Navigate to="/system/base-admin" replace />;
}

Add the API routes for auth checks in Laravel's api.php:

Route::middleware('auth:customer')->get('/customer/check-auth', function () {
    return response()->json(['authenticated' => true]);
});

Route::middleware('auth:admin')->get('/admin/check-auth', function () {
    return response()->json(['authenticated' => true]);
});

3. Route Setup

Configure your React router to use the protected route components:

import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import CustomerLogin from './components/CustomerLogin';
import AdminLogin from './components/AdminLogin';
import CustomerDashboard from './components/CustomerDashboard';
import AdminDashboard from './components/AdminDashboard';
import ProtectedCustomerRoute from './components/ProtectedCustomerRoute';
import ProtectedAdminRoute from './components/ProtectedAdminRoute';

function App() {
    return (
        <Router>
            <Routes>
                {/* Public Routes */}
                <Route path="/login" element={<CustomerLogin />} />
                <Route path="/system/base-admin" element={<AdminLogin />} />

                {/* Protected Customer Routes */}
                <Route element={<ProtectedCustomerRoute />}>
                    <Route path="/customer/dashboard" element={<CustomerDashboard />} />
                </Route>

                {/* Protected Admin Routes */}
                <Route element={<ProtectedAdminRoute />}>
                    <Route path="/system/admin/dashboard" element={<AdminDashboard />} />
                </Route>

                {/* Fallback Route */}
                <Route path="*" element={<Navigate to="/login" replace />} />
            </Routes>
        </Router>
    );
}

export default App;

4. Logout Handling

Add logout functionality to each dashboard component. For example, in CustomerDashboard.jsx:

import { useNavigate } from 'react-router-dom';

export default function CustomerDashboard() {
    const navigate = useNavigate();

    const handleLogout = async () => {
        try {
            await fetch('/customer/logout', {
                method: 'POST',
                headers: {
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
                }
            });
            navigate('/login');
        } catch (err) {
            console.error('Logout failed:', err);
        }
    };

    return (
        <div>
            <h2>Customer Dashboard</h2>
            <button onClick={handleLogout}>Logout</button>
            {/* Dashboard content */}
        </div>
    );
}

Repeat this for the admin dashboard, using the /system/admin/logout endpoint and redirecting to /system/base-admin.

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

火山引擎 最新活动