You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel集成AD LDAP登录遇Nginx 403 Forbidden问题求助

问题背景

我正在基于Laravel实现Active Directory(AD)LDAP登录功能,已完成以下配置:

  • 编写了LDAP认证控制器逻辑,通过AD验证用户凭据并关联本地userRole表的权限
  • 配置了AD服务器地址、LDAP绑定DN,创建了登录表单的GET/POST路由
  • 修改了.env和config/app.php的协议配置,关闭了secure protocol
  • 创建userRole表用于邮箱匹配与权限校验
  • 调整config/auth.php的guards和providers,指定用户模型为UserRole

当前核心问题:访问应用根路径/时触发Nginx 403 Forbidden错误;根目录存在php/html文件时可正常访问,移除后就会报错,无法进入Laravel应用并自动跳转至登录页。


代码片段

LdapAuthController.php

class LdapAuthController extends Controller
{
    public function ldapLogin(Request $request)
    {
        if ($request->isMethod('post')) {
            if (isset($request->username) && isset($request->password)) {
                $adServer = "ldap://domaincontroller.mydomain.com";
                $ldap = ldap_connect($adServer);
                $username = $request->username;
                $password = $request->password;
                $ldaprdn = 'mydomain' . "\\" . $username;
                ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
                ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
                $bind = @ldap_bind($ldap, $ldaprdn, $password);

                if ($bind) {
                    $filter = "(sAMAccountName=$username)";
                    $result = ldap_search($ldap, "dc=MYDOMAIN,dc=COM", $filter);
                    if ($result) {
                        $info = ldap_get_entries($ldap, $result);
                        $email = $info[0]["mail"][0];

                        $userRole = UserRole::where('email', $email)->first();

                        if ($userRole) {
                            session(['user_role' => $userRole->role]);
                        }
                    } else {
                        return back()->with('error', 'LDAP search failed');
                    }

                    @ldap_close($ldap);
                    return redirect()->route('dashboard');
                } else {
                    return back()->with('error', 'Invalid email address / password');
                }
            }
        } else {
            return view('auth.login');
        }
    }
}

web.php

Route::get('/login', function () {
    return view('auth.ldap-login-form');
})->name('login');

Route::post('/login', [LdapAuthController::class, 'ldapLogin'])->name('login.submit');

Route::group(['namespace' => 'App\Http\Controllers'], function () {
    Route::group(['middleware' => ['guest']], function () {
        Route::post('/ldap-login', [LdapAuthController::class, 'ldapLogin'])->name('ldap-login');
    });

    Route::group(['middleware' => ['auth']], function () {
        Route::get('/logout', 'LogoutController@logout')->name('logout.logout');

        Route::group(['middleware' => ['checkUserRole:admin']], function () {
            // 管理员路由
        });
    });
});

config/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\UserRole::class,
    ],
],

解决方案

一、先解决Nginx 403错误

这是因为Nginx没有正确将请求转发到Laravel的入口文件,或者目录配置有误:

  1. 修正Nginx站点配置
    确保配置文件中root指向Laravel项目的public目录,并且配置try_files规则让所有请求经过index.php处理:

    server {
        listen 80;
        server_name your-domain.com;
        root /path/to/your/laravel-project/public;
    
        index index.php index.html index.htm;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 根据你的PHP版本调整
        }
    
        location ~ /\.ht {
            deny all;
        }
    }
    

    配置完成后重启Nginx:sudo systemctl restart nginx

  2. 修复目录权限
    确保Nginx进程用户(通常是www-data)拥有Laravel目录的读写权限:

    sudo chown -R www-data:www-data /path/to/your/laravel-project
    sudo chmod -R 755 /path/to/your/laravel-project
    sudo chmod -R 775 /path/to/your/laravel-project/storage /path/to/your/laravel-project/bootstrap/cache
    

二、完善Laravel路由与认证逻辑

  1. 添加根路径路由
    在web.php中配置根路径的跳转规则,未登录用户自动跳转到登录页:

    Route::get('/', function () {
        return Auth::check() ? redirect()->route('dashboard') : redirect()->route('login');
    });
    
  2. 修正LDAP认证的Auth登录逻辑
    当前代码仅存储了user_role会话,但未让Laravel的Auth系统识别用户登录,导致auth中间件无法生效。修改LdapAuthController中绑定成功后的代码:

    if ($bind) {
        $filter = "(sAMAccountName=$username)";
        $result = ldap_search($ldap, "dc=MYDOMAIN,dc=COM", $filter);
        if ($result) {
            $info = ldap_get_entries($ldap, $result);
            $email = $info[0]["mail"][0];
    
            $userRole = UserRole::where('email', $email)->first();
    
            if ($userRole) {
                // 让Laravel Auth系统登录该用户
                Auth::login($userRole);
                session(['user_role' => $userRole->role]);
            } else {
                return back()->with('error', '无系统访问权限,请联系管理员');
            }
        } else {
            return back()->with('error', 'LDAP搜索失败');
        }
    
        @ldap_close($ldap);
        return redirect()->route('dashboard');
    }
    

    同时确保UserRole模型继承Laravel的用户基类:

    namespace App\Models;
    
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class UserRole extends Authenticatable
    {
        protected $table = 'user_roles';
    }
    
  3. 清理重复路由
    移除web.php中重复的/ldap-login路由,避免路由冲突:

    // 删除这段重复路由
    Route::group(['middleware' => ['guest']], function () {
        Route::post('/ldap-login', [LdapAuthController::class, 'ldapLogin'])->name('ldap-login');
    });
    

三、清除缓存验证

执行以下命令清除Laravel缓存,确保配置生效:

php artisan cache:clear
php artisan config:clear
php artisan route:clear

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:05:55