samysdk/laravel-external-authentication

Laravel身份验证守卫,用于基于由认证反向代理设置的头部或环境变量的身份验证。

v0.1.1 2023-06-08 15:53 UTC

This package is auto-updated.

Last update: 2024-09-07 14:40:17 UTC


README

Laravel身份验证包,根据HTTP请求头部或由外部身份验证源(如Apache的基本身份验证、SAML2 SSO通过mod_auth_mellon或使用Nginx的http_auth_request模块)设置的属性或属性进行用户认证。

此包专注于认证用户并设置用户模型上的属性或属性,这些属性或属性通过外部身份提供者设置。

Build Status

安全

如果您依赖于HTTP头部来确定用户是否已认证,您必须确保这些头部已从受信任的来源发送到您的Laravel应用,并且没有被客户端伪造。

例如

  • 运行具有http_auth_request模块的Nginx,设置HTTP头部并将请求代理到同一虚拟机上运行应用程序的php-fpm后端。
  • 使用Apache和mod_auth_mellon进行SAML SSO,在同一服务器上为PHP设置环境变量

这两种情况应该是安全的,前提是确保当没有用户认证时,Web服务器将变量设置为空值

此外,如果您的身份验证服务器(如上面示例中的Apache或Nginx)正在将请求代理到一个或多个不同的服务器(通过网络),您应确保PHP仅对那些特定的上游服务器响应,以避免网络上的其他用户能够使用伪造的头部发出请求。

快速入门

  1. 安装:composer require samyapp/laravel-external-authentication

  2. 发布配置

    php artisan vendor:publish --provider="SamYapp\LaravelExternalAuth\ExternalAuthServiceProvider"
    
  3. 配置应用程序以使用外部守卫

    config/auth.php:

    'guards' => [
         'web' => [
             'driver' => 'external-auth',
             'provider' => 'users',
         ],
     ],
    
  4. 如果您的应用程序使用瞬态用户,请配置用户提供者和模型

    config/auth.php:

    'providers' => [
         'users' => [
             'driver' => 'transient',
             'model' => '\SamYapp\LaravelExternalAuth\TransientUser',
         ],
     ],
    
  5. 编辑config/external-auth.php以使用您的配置

  6. 将身份验证添加到要保护的路线中。

  7. 以与任何正常Laravel应用相同的方式访问已认证用户。您的config/external-auth.php中定义的任何用户属性都应在您的用户模型上可用。

故障排除

在配置外部身份验证源(如Apache mod_mellon_auth)时,查看它向PHP发送哪些属性和值可能很有用。

您可以通过在您的配置中将'logInput' => true,启用此数据的记录(使用您的应用程序的Laravel日志配置),您还必须确保'logLevel'至少设置为您的应用程序日志级别的最小值(例如,info、debug、warning等)。

请注意,这将(除非开发Mode = true)将Request::server()的内容输出到您的Laravel日志中,因此仅在故障排除至关重要时才启用。

开发和测试配置

配置身份验证服务(如Apache mod mellon)而不是在开发期间配置身份验证服务,您可以启用开发模式并指定您想要设置的头部

config/external-auth.php

<?php

return [
    // ... other configuration options
    'attributeMap' => [
        'username' => 'X-USERNAME',
        'role' => 'X-USER-ROLE',
    ],
 
    'credentialAttributes' => [
        'username',
    ],
 
    'developmentMode' => true,
    'developmentAttributes' => [
        'X-USERNAME' => 'foo',
        'X-USER-ROLE' => 'admin',
        // .. any other attributes that would be set by your real auth provider...
    ]
]

属性名称应与您实时环境中设置的名称相同。

在上面的示例中,经过身份验证的用户将是一个用户名为'foo'的用户,用户模型将具有将'role'属性设置为'value'admin'的值。

身份验证用户

ExternalAuthGuard可以以下方式之一与您的应用程序的用户模型一起工作

  1. 用户存在于您的应用程序中(配置的用户提供者可以检索与凭据匹配的用户)并且如果凭据属性与现有用户不匹配,则身份验证失败。
  2. 用户不存在于您的应用程序中,但应创建一个"瞬态"用户模型来表示每个请求中经过身份验证的用户。

授权用户

使用标准的Laravel方法为特定的路由或操作授权用户。

配置

处理现有用户和用户模型

ExternalAuthGuard使用与默认Laravel SessionGuard相同的配置方式在您的config/auth.php中配置的用户提供者和用户模型,通过从config/external-auth.php中的credentialAttributes设置中命名的服务器命名值调用UserProvider::retrieveByCredentials()

创建"缺失"用户

如果您希望在守卫首次为它们进行身份验证时在数据库中"按需"创建用户,您可以监听UnknownUserAuthenticating事件,该事件在请求中所有预期用户属性都存在但用户提供者找不到现有用户时发出。

您可以在类似于以下示例的监听器中创建和持久化用户(您可能需要添加一些验证)

app/Providers/EventServiceProvider.php

    // class EventServiceProvider
    /**
     * Register any events for your application.
     */
    public function boot(): void
    {
        Event::listen(function (UnknownUserAuthenticating $event) {
            $user = new \App\Models\User();
            foreach ($event->attributes as $name => $value) {
                $user->$name = $value;
            }
            $user->save();
            $event->guard->login($user);
        });
    }

或者,您可能希望在用户通过外部身份验证进行身份验证但没有在您的应用程序中找到匹配的用户帐户时进行记录。

更新用户属性

如果您需要将您的应用程序的用户表与从外部身份验证提供程序(例如,名称、角色或某些其他属性)传递的属性值同步,您可以监听在守卫的login($user)方法被调用时触发的Illuminate\Auth\Events\Login事件。

此事件将在其$user属性中具有经过身份验证的User模型,该模型将具有外部身份验证源设置的属性值。

对于标准的Laravel用户模型,您只需调用$event->user->save()即可将其与您的应用程序数据库同步,例如

app/Providers/EventServiceProvider.php

    // class EventServiceProvider
    /**
     * Register any events for your application.
     */
    public function boot(): void
    {
        Event::listen(function (Illuminate\Auth\Events\Login $event) {
            $event->user->save();
        });
    }

处理"瞬态"用户

ExternalAuthGuard可用于没有单独的用户数据库表的应用程序,完全依赖于外部身份验证源来设置定义用户的属性。

您可以使用提供的TransientUserProvider,该提供程序由包服务提供者自动注册,接受从外部身份验证源传递的属性,并将返回一个用户对象,其中每个属性的值都分配给它,而不会尝试从数据库中检索现有用户。

可以将Transient用户提供程序配置为使用任何类作为创建的用户对象。

该包包括一个非常简单的TransientUser对象,它仅允许设置和获取属性值,但可以与任何允许设置和获取属性的字类一起使用。

要将TransientUserProvider配置为该守卫的用户提供程序,请编辑您的身份验证配置

config/auth.php


  'guards' => [
      'web' => [
         'driver'   => 'external-auth',
         'provider' => 'transient',
      ],
      
      // ... additional guard configuration

   ],

   'providers' => [
      'transient' => [
         'driver' => 'transient-user',
         'model'  => \SamYapp\LaravelExternalAuth\TransientUser::class,
      ],

      // ... other provider configuration
   ],

要使用自己的类(例如App\Models\User)作为经过身份验证的用户对象,只需将上述providers.transient.model参数设置为以下内容,例如

   'providers' => [
      'transient' => [
         'driver' => 'transient-user',
         'model'  => \App\Models\User::class,
      ],

      // ... other provider configuration
   ],

附加选项

自定义属性映射

如果您需要额外的逻辑将外部设置的属性映射到您的用户模型,您可以创建一个可调用的函数,并将mapAttributes配置设置设置为它。

请参阅DefaultAttributeMapper实现以供参考。

例如,创建一个名为\My\App\MyAttributeMapper的类,并包含一个静态方法mapAttributes(AuthConfig $config, array $input): array,然后在您的externa-auth.php配置文件中设置

config/external-auth.php

return [
    // ... configuration...

    'mapAttributes' => '\My\App\MyAttributeMapper::mapAttributes',

    // ... more config
];

身份验证守卫驱动程序ID

要指定您的应用程序应使用ExternalAuthGuard来认证用户,请在您的config/auth.php中将守卫驱动程序的名称指定为external-auth

这是ExternalAuthServiceProvider默认情况下注册守卫的名称。

如果您需要使用不同的名称,可以设置id配置选项(同时确保更新守卫驱动程序的值以匹配)。

config/external-auth.php

return [    // ... configuration...

    'id' => 'my-external-auth',

    // ... more config
];