fos1/sf-doctrine-guard-plugin

Symfony的身份验证和授权插件

安装次数: 11,752

依赖关系: 0

建议者: 0

安全: 0

星标: 1

关注者: 4

分支: 15

类型:symfony1-plugin

v1.5.9 2019-05-05 10:59 UTC

This package is auto-updated.

Last update: 2024-09-05 22:19:03 UTC


README

sfDoctrineGuardPlugin 是一个 symfony 插件,它提供了比 symfony 标准安全特性更高级的身份验证和授权功能。

它提供了一个模型(用户、组和权限对象)以及模块(后端和前端),使您可以在配置插件的情况下,在一分钟内安全地保护您的 symfony 应用程序。

从版本 5.0.0(1.4 稳定分支)开始,sfDoctrineGuardPlugin 还提供了通过网站申请账户的选项(默认情况下已禁用),以及重置您忘记的密码的能力。出于安全考虑,密码重置需要您知道与账户关联的电子邮件地址,并且能够在此处接收邮件。但是,在 5.0.0 中,申请账户尚不需要接收电子邮件。

5.x 系列在与早期版本迁移时可能需要大量的迁移工作。请参阅升级部分以获取更多信息。

注意

此插件最初由 Fabien Potencier 为 Symfony1 开发,后来移至 GitHub 并由 LExpress 群组更新(https://github.com/LExpress/sfDoctrineGuardPlugin)。

将此插件置于 FriendsOfSymfony1 组织下并不意味着此模块目前正在维护或积极开发。目的是提供一个集中地点,将过时的插件放置于此,以减少因(任何合同/奇怪/其他原因)而需要维护 Symfony1 应用程序的组织进行的分支数量。

如果您计划基于 Symfony 的新项目,请使用最新和维护的 Symfony 版本,您不会后悔的 ;)

安装

  • 使用 composer 安装插件

    composer require fos1/sf-doctrine-guard-plugin
    
  • config/ProjectConfiguration.class.php 中激活插件

    class ProjectConfiguration extends sfProjectConfiguration
    {
      public function setup()
      {
        $this->enablePlugins(array(
          'sfDoctrinePlugin',
          'sfDoctrineGuardPlugin',
          '...'
        ));
      }
    }
  • 重建您的模型

    symfony doctrine:build-model
    symfony doctrine:build-sql
    
  • 从零开始更新您的数据库表(这将删除所有现有表,然后重新创建它们)

    symfony doctrine:insert-sql
    

    或者使用一条命令完成所有操作

    symfony doctrine-build-all-reload frontend
    

    或者您可以使用 data/sql/plugins.sfGuardAuth.lib.model.schema.sql 中生成的 SQL 语句创建新表

  • 加载默认的 fixtures(可选 - 它创建一个超级管理员用户)

    mkdir data/fixtures/
    cp plugins/sfDoctrineGuardPlugin/data/fixtures/fixtures.yml.sample data/fixtures/sfGuard.yml
    
    symfony doctrine:data-load frontend # replace frontend with the name of one of your application
    
  • settings.yml 中启用一个或多个模块(可选)

    • 对于您的后端应用程序:sfGuardUser,sfGuardGroup,sfGuardPermission

          all:
            .settings:
              enabled_modules:      [default, sfGuardGroup, sfGuardUser, sfGuardPermission]
      

    请注意:这些模块默认情况下不安全,因为我们无法猜测您想要的政策。请阅读下面的“保护您的应用程序”部分。

    • 对于您的前端应用程序:sfGuardAuth

          all:
            .settings:
              enabled_modules:      [default, sfGuardAuth]
      

    不要安全 sfGuardAuth,这是允许用户登录的模块。

  • 清除您的缓存

    symfony cc
    
  • 可选地,将“记住我”过滤器添加到 filters.yml 中,位于安全过滤器之上

    remember_me:
      class: sfGuardRememberMeFilter
    
    security: ~
    

升级

5.0.x 系列添加了多个新表,向现有表添加了列,并且更改了模式中所有关系的名称。

这需要两种类型的更改:数据库模式更改以及在某些情况下代码的更改。我们将依次查看这些问题。

更新您的模式

模式中存在三种基本更改

  • 所有主键 ID 列都已更改为 8 字节整数
  • sfGuardUser 表中添加了新列,该表现在包含 first_namelast_nameemail_address 信息
  • 一个新的 sfGuardForgotPassword 表用于验证密码重置请求和账户创建请求
升级到 8 字节整数

使用Doctrine的generate-migrations-diff任务来更新架构会很方便,但遗憾的是,虽然这是一个强大的工具,但它无法解决如何在不出现外键错误的情况下将ID列更改为8字节的问题。您可以自己编写迁移,或者直接使用SQL ALTER TABLE语句。如果您选择这样做,需要先删除外键索引(当然不是列,只是索引),然后更改ID列类型,最后再次创建外键索引。我们建议在此过程中锁定数据库。

您也可以在现有的数据库中保持ID类型的原样。这样做会容易得多。如果您选择这种方法,请确保按照以下说明创建新的sfGuardForgotPassword表,使用4字节整数,就像您旧表一样。

添加新列

sf_guard_user表中新增了三列。您可以使用以下SQL语句添加这些列

ALTER TABLE sf_guard_user ADD COLUMN first_name varchar(255) DEFAULT NULL;
ALTER TABLE sf_guard_user ADD COLUMN last_name varchar(255) DEFAULT NULL;
ALTER TABLE sf_guard_user ADD COLUMN email_address varchar(255) DEFAULT '';

接下来,您应指定电子邮件地址必须是唯一的。如果您的现有系统中用户根本没有任何电子邮件地址字段(例如,您没有配置文件表,或者其中没有电子邮件地址),这会引发问题。您可以通过以下方式作为临时解决方案

UPDATE sf_guard_user SET email_address = username;

这确保了唯一性,尽管实际上并不提供有用的电子邮件地址。如果您有一个包含电子邮件地址的配置文件表,更好的做法是从那里导入您的电子邮件地址

UPDATE sf_guard_user,sf_guard_profile SET sf_guard_user.email_address = sf_guard_profile.email_address WHERE sf_guard_user.id = sf_guard_profile.id;

现在您可以为该列创建索引并使其唯一

ALTER TABLE sf_guard_user ADD UNIQUE KEY `email_address` (`email_address`);
添加sfGuardForgotPassword表

您可以使用以下SQL代码完成此操作。

如果您希望继续使用4字节ID

CREATE TABLE sf_guard_forgot_password (id INT AUTO_INCREMENT, user_id INT NOT NULL, unique_key VARCHAR(255), expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX user_id_idx (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = INNODB;

如果您已经升级了ID

CREATE TABLE sf_guard_forgot_password (id BIGINT AUTO_INCREMENT, user_id BIGINT NOT NULL, unique_key VARCHAR(255), expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX user_id_idx (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = INNODB;

更新您的代码

如果您尚未迁移数据库架构,请首先这样做(见上方)。否则,您将失去使用Doctrine迁移的选项。

更新架构后,您还需要更新代码以适应这些变化。

首先重建模型、表单和过滤器基础类。只要您遵循标准实践并保留Base类不变,这将不会损坏您自己模型类中的任何自定义代码

./symfony doctrine:build --all-classes

其次,检查您的Doctrine代码,查找使用sfGuardUsersfGuardGroup等定义的关联的地方。为了方便和遵循Symfony最佳实践,这些关联的名称已经更改。

最常见的已更改关联如下

$group->users现在为$group->Users(大写)$group->permissions现在为$group->Permissions(大写)$user->groups现在为$user->Groups(大写)$user->permissions现在为$user->Permissions(大写)

sfGuardUserPermissionsfGuardGroupPermission上的不常用关联也已更改。它们都是大写,并且没有sfGuard前缀。那些有时编写自定义查询以定位具有特定权限的用户的人需要注意这一点。

保护您的应用程序

要保护symfony应用程序

  • settings.yml中启用模块sfGuardAuth

    all:
      .settings:
        enabled_modules: [..., sfGuardAuth]
    
  • settings.yml中更改默认登录和安全模块

    login_module:           sfGuardAuth
    login_action:           signin
    
    secure_module:          sfGuardAuth
    secure_action:          secure
    
  • myUser.class.php中更改父类

    class myUser extends sfGuardSecurityUser
    {
    }
  • 可选地添加以下路由规则到routing.yml

    sf_guard_signin:
      url:   /login
      param: { module: sfGuardAuth, action: signin }
    
    sf_guard_signout:
      url:   /logout
      param: { module: sfGuardAuth, action: signout }
    
    sf_guard_register:
      url:   /register
      param: { module: sfGuardRegister, action: index }
    
    sf_guard_forgot_password:
      url:   /forgot_password
      param: { module: sfGuardForgotPassword, action: index }
    
    sf_guard_forgot_password_change:
      url:   /forgot_password/:unique_key
      class: sfDoctrineRoute
      options: { model: sfGuardForgotPassword, type: object }
      param: { module: sfGuardForgotPassword, action: change }
      requirements:
        sf_method: [get, post]
    

    您可以自定义每个路由的url参数。注意:您必须有一个@homepage路由规则(在用户登出时使用)

    如果启用了模块sfGuardAuth,则插件会自动注册这些路由,除非您在app.yml配置文件中将sf_guard_plugin_routes_register设置为false

    all:
      sf_guard_plugin:
        routes_register: false
    
  • security.yml中保护某些模块或您的整个应用程序

    default:
      is_secure: true
    
  • 已完成。现在,如果您尝试访问一个安全页面,您将被重定向到登录页面。如果您已加载默认的配置文件,请使用用户名 admin 和密码 admin 尝试登录。

  • 如果您默认没有对整个站点进行安全设置,请确保您特别保护了 sfGuardUsersfGuardGroupsfGuardPermission 模块!否则匿名用户可以随时创建用户、组和权限。这是在 sfDoctrineGuardPlugin 网站上常见的疏忽。

管理您的用户、权限和组

要能够管理您的用户、权限和组,sfDoctrineGuardPlugin 附带了 3 个模块,可以将这些模块集成到您的后端应用程序中。这些模块是通过 symfony 管理生成器自动生成的。

  • settings.yml 中启用模块

    all:
      .settings:
        enabled_modules: [..., sfGuardGroup, sfGuardPermission, sfGuardUser]
    
  • 如果您没有对整个站点进行安全设置,请通过 security.yml 对这些模块进行安全设置。否则,匿名用户可以创建和删除用户

  • 使用默认路由 sf_guard_user 访问模块

    http://www.example.com/backend.php/guard/users

账户申请

一些站点管理员可能希望允许公众成员申请账户。从 5.0.0 版本开始,这个功能在 sfDoctrineGuardPlugin 中可用。

要启用此功能,您必须启用 sfGuardRegister 模块,然后为用户提供一个链接到 sfGuardRegister/index 动作的链接。

[待完善] [待完善:记录忘记密码功能]

自定义 sfGuardAuth 模块模板

默认情况下,sfGuardAuth 模块附带 2 个非常简单的模板

  • signinSuccess.php
  • secureSuccess.php

如果您想自定义这些模板之一

  • 在您的应用程序中创建一个 sfGuardAuth 模块(不要使用 init-module 任务,只需创建一个 sfGuardAuth 目录)

  • sfGuardAuth/templates 目录中创建一个您想要定制的模板名称的模板

  • symfony 现在将渲染您的模板而不是默认模板

自定义 sfGuardAuth 模块操作

如果您想自定义或添加 sfGuardAuth 的方法

  • 在您的应用程序中创建一个 sfGuardAuth 模块

  • 在您的 actions 目录中创建一个 actions.class.php 文件,该文件继承自 BasesfGuardAuthActions(不要忘记包含 BasesfGuardAuthActions,因为它不能由 symfony 自动加载)

      require_once(sfConfig::get('sf_plugins_dir').'/sfDoctrineGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php');
    
      class sfGuardAuthActions extends BasesfGuardAuthActions
      {
        public function executeNewAction()
        {
          return $this->renderText('This is a new sfGuardAuth action.');
        }
      }

sfGuardSecurityUser

此类继承自 Symfony 的 sfBasicSecurityUser 类,并用于 symfony 应用程序中的 user 对象。(请记住,您之前更改了 myUser 基类。)

要访问它,您可以在操作中或模板中使用标准的 $this->getUser()$sf_user

sfGuardSecurityUser 添加了一些有用的方法

  • signIn()signOut() 方法
  • getGuardUser(),它返回 sfGuardUser 对象
  • 一些代理方法,可以直接访问 sfGuardUser 对象

例如,要获取当前用户名

  $this->getUser()->getGuardUser()->getUsername()

  // or via the proxy method
  $this->getUser()->getUsername()

超级管理员("超级管理员")标志

为了防止鸡生蛋的问题,sfDoctrineGuardPlugin 有一个"超级管理员"的概念。超级管理员用户可以绕过所有凭证检查。

超级管理员标志不能通过 sfGuardUser 管理模块设置,您必须直接在数据库中设置标志或使用提供的 Symfony 任务

symfony guard:promote admin

验证器

sfDoctrineGuardPlugin 附带了一个验证器,您可以在您的模块中使用:sfGuardUserValidator

此验证器用于在登录用户之前由 sfGuardAuth 模块验证用户名和密码。

使用外部方法检查用户密码

如果您不想将密码存储在数据库中,因为您已经有了一个 LDAP 服务器、.htaccess 文件,或者如果您在其他表中存储密码,您可以在 app.yml 中提供一个自己的 checkPassword 可调用(静态方法或函数)。

all:
  sf_guard_plugin:
    check_password_callable: [MyLDAPClass, checkPassword]

当symfony调用$this->getUser()->checkPassword()方法时,它将调用你的方法或函数。你的函数必须接受两个参数,第一个是用户名,第二个是密码。它必须返回true或false。以下是此类函数的模板

  function checkLDAPPassword($username, $password)
  {
    $user = LDAP::getUser($username);
    if ($user->checkPassword($password))
    {
      return true;
    }
    else
    {
      return false;
    }
  }

更改存储密码所使用的算法

默认情况下,密码以sha1()哈希的形式存储。但你可以通过在app.yml中使用任何可调用的函数来更改这一点

all:
  sf_guard_plugin:
    algorithm_callable: [MyCryptoClass, MyCryptoMethod]

或者

all:
  sf_guard_plugin:
    algorithm_callable: md5

由于算法为每个用户存储,因此你可以稍后改变主意,而无需重新生成当前用户的密码。

更改“记住我”cookie的名称或有效期

默认情况下,“记住我”功能创建一个名为sfRemember的cookie,有效期为15天。你可以在app.yml中更改此行为

all:
  sf_guard_plugin:
     remember_key_expiration_age:  2592000   # 30 days in seconds
     remember_cookie_name:         myAppRememberMe

自定义sfGuardAuth的重定向处理

在成功登录后,可以将用户重定向到其个人资料,或者在注销时重定向到特定的页面。

你可以在app.yml中更改重定向设置

all:
  sf_guard_plugin:
    success_signin_url:      @my_route?param=value # the plugin uses the referer as default
    success_signout_url:     module/action         # the plugin uses the referer as default