lexpress / sf-doctrine-guard-plugin
symfony的认证管理插件
Requires
- composer/installers: ~1.0
This package is not auto-updated.
Last update: 2020-01-24 15:04:44 UTC
README
sfDoctrineGuardPlugin
是一个symfony插件,它提供了超出symfony标准安全特性的认证和授权功能。
它提供了一个模型(用户、组和权限对象)和模块(后端和前端),通过可配置的插件,可以在一分钟内保护您的symfony应用程序。
从版本5.0.0(1.4稳定分支)开始,sfDoctrineGuardPlugin
还提供了通过网站申请账户的选项(默认情况下是禁用的),以及重置您忘记的密码的能力。出于安全考虑,密码重置需要您知道与账户关联的电子邮件地址,并且能够接收那里的邮件。然而,在5.0.0中申请账户尚不需要接收电子邮件。
5.x系列在从早期版本迁移时可能需要大量的迁移工作。请参阅升级部分以获取更多信息。
安装
-
安装插件(通过composer)
composer require lexpress/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语句创建新的表 -
加载默认的固定数据(可选 - 它创建了一个超级管理员用户)
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_name
、last_name
和email_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代码,查找使用为sfGuardUser
、sfGuardGroup
等定义的关联的地方。出于方便和遵循Symfony最佳实践的考虑,这些关联的名称已经更改。
更改的最常用的关联如下
$group->users现在为$group->Users(大写)$group->permissions现在为$group->Permissions(大写)$user->groups现在为$user->Groups(大写)$user->permissions现在为$user->Permissions(大写)
在sfGuardUserPermission
和sfGuardGroupPermission
上的不常用关联也发生了变化。它们是大写的,并且没有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
登录。 -
如果您默认没有对整个网站进行安全设置,那么请确保您特别保护了
sfGuardUser
、sfGuardGroup
和sfGuardPermission
模块!否则,匿名用户可以在任何时候创建用户、组和权限。这是在sfDoctrineGuardPlugin
网站上常见的疏忽。
管理您的用户、权限和组
为了能够管理您的用户、权限和组,sfDoctrineGuardPlugin
包含了 3 个模块,这些模块可以集成到您的后端应用程序中。这些模块是利用 symfony 管理生成器自动生成的。
-
在
settings.yml
中启用这些模块all: .settings: enabled_modules: [..., sfGuardGroup, sfGuardPermission, sfGuardUser]
-
如果您没有对整个网站进行安全设置,请记得通过
security.yml
对这些模块进行安全设置。否则,匿名用户可以创建和删除用户。 -
使用默认路由
sf_guard_user
访问这些模块
申请账户
一些网站管理员希望允许公众成员申请账户。从 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()
超级管理员(super administrator)标志
为了避免鸡生蛋的问题,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