卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章17363本站已运行3327

Yii2编程:安全性

Yii2编程:安全性

如果您问“Yii 是什么?”查看Yii 框架简介,其中回顾了 Yii 的优点并包含 Yii 2.0 的概述。

在这个使用 Yii2 编程系列中,我将指导读者使用 Yii2 PHP 框架。如果您计划与公众共享您的应用程序,则需要它是安全的,并且最好从一开始就计划好。幸运的是,从像 Yii 这样的框架开始,这比其他框架要容易得多。正如 Yii 的功能中所述:

Yii 配备了许多安全措施来帮助防止您的 Web 应用程序遭受 SQL 注入、跨站点脚本 (XSS)、跨站点请求伪造 (CSRF) 和 cookie 篡改等攻击。

在本教程中,我将引导您了解 Yii 应用程序框架内的基本安全概念。而且,如果您有兴趣,随着我们的启动系列中的会议计划器应用程序接近 Alpha 版本,未来的几集将致力于确保该应用程序的安全。

在我们开始之前,请记住,我确实尝试参与下面的讨论。如果您有问题或主题建议,请在下面发表评论或通过 Twitter @reifman 与我联系。

注意:如果您注意到“Programming Yii”系列剧集之间存在间隙,那是因为我去年不得不进行脑部手术。感谢您的耐心和支持——很高兴再次定期撰写文章,我期待着继续报道 Yii2。

Yii 安全基础知识

如果您是 Web 应用程序安全方面的新手,那么关于 Yii 的产品有很多内容需要了解。我将尽力根据最好的 Yii 2.0 文档提供概述。 Yii 团队将安全性分为七个关键领域:

  1. 身份验证
  2. 授权
  3. 使用密码
  4. 密码学
  5. 查看安全性
  6. 身份验证客户端
  7. 最佳实践

让我们开始一一深入研究这些内容。

1。身份验证

Ilko Kacharov 的 Yii 框架安全演示提供了一些有用的幻灯片,总结了身份验证的目标(以及以下子主题,授权)。本质上,以下是这些主题需要回答的问题:

  • 用户是谁?
  • 用户就是他们所说的那样吗?
  • 用户是否有权访问资源?
  • 用户是否有权执行某项操作?
  • 用户是否有权对资源执行操作?

用户模型和身份接口

Yii 的 yii/web/User 类与 yiiwebIdentityInterface 集成,以管理应用程序中用户的身份验证状态。

去年 11 月,我写了一篇关于 Yii 高级应用程序模板的教程。高级模板的优点之一是它提供了用户模型与 ActiveRecord 和数据库的预构建集成。因此,您的应用程序立即提供数据库驱动的身份验证。

用户模型允许您以编程方式登录和注销用户:

  • login() 设置指定的身份并记住会话和 cookie 中的身份验证状态。
  • logout() 将用户标记为访客,并清除会话和 Cookie 中的相关信息。
  • setIdentity():在不接触会话或 cookie 的情况下更改用户身份,最适合 API 功能。

$isGuest 属性确定当前用户是否已登录。当用户注销时,它为 null,但否则返回 IdentityInterface 的实例。

本质上,您需要一个扩展 ActiveRecord 并实现支持 IdentityInterface 的方法的 User 类,如下所示:

'
<?php

use yiidbActiveRecord;
use yiiwebIdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    public static function tableName()
    {
        return 'user';
    }

    /**
     * Finds an identity by the given ID.
     *
     * @param string|integer $id the ID to be looked for
     * @return IdentityInterface|null the identity object that matches the given ID.
     */
    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    /**
     * Finds an identity by the given token.
     *
     * @param string $token the token to be looked for
     * @return IdentityInterface|null the identity object that matches the given token.
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
    }

    /**
     * @return int|string current user ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return string current user auth key
     */
    public function getAuthKey()
    {
        return $this->auth_key;
    }

    /**
     * @param string $authKey
     * @return boolean if auth key is valid for current user
     */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }
}

此外,在创建用户之前,应用程序会生成一个随机字符串作为授权密钥。这可以用在“忘记密码”电子邮件或其他基于电子邮件的登录链接中:

'
class User extends ActiveRecord implements IdentityInterface
{
    ......
    
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($this->isNewRecord) {
                $this->auth_key = Yii::$app->security->generateRandomString();
            }
            return true;
        }
        return false;
    }
}

授权

Yii 提供了两种内置的授权方法。更简单的访问控制列表 (ACL) 确定允许哪些用户或进程对资源执行操作,而更密集的基于角色的访问控制 (RBAC) 可帮助您通过定义角色来管理访问权限。在RBAC中,只有具有特定角色的用户或系统任务才能执行特定操作。

访问控制列表

ACL 有时也称为访问控制过滤器 (ACF)。 Yii 在 yiifiltersAccessControl 中提供 ACL 支持。它非常适合只需要简单访问控制的应用程序。这是我迄今为止在 Meeting Planner 中使用的内容。

以下是常见 SiteController 的示例,该示例配置访问行为以过滤对可用操作(通常是页面)的访问。在本例中,ACL 作用于注册、登录和注销。 '?' 表示任何用户都可以访问登录和注册页面,而 '@' 表示仅允许登录或经过身份验证的用户访问。在下面的示例中,只有登录的用户才能注销:

'
use yiiwebController;
use yiifiltersAccessControl;

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['login', 'logout', 'signup'],
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => ['login', 'signup'],
                        'roles' => ['?'],
                    ],
                    [
                        'allow' => true,
                        'actions' => ['logout'],
                        'roles' => ['@'],
                    ],
                ],
            ],
        ];
    }
    // ...
}

随着控制器的增长,每个新操作都需要在访问控制规则中定义。而且,随着应用程序的增长,每个控制器及其所有操作都需要集成 ACL 过滤以确保安全。

基于角色的访问控制

基于角色的访问控制(RBAC)提供了更强大的身份验证系统,但也需要更多的前期设计和实现。

使用 RBAC,您可以通过可以继承(或不可继承)的角色来定义身份验证,并将角色应用于用户。您还可以定义角色规则。 RBAC 实现可能会变得相当复杂。

在下图中,管理员可以执行任何任务,作者可以创建帖子并更新自己的帖子。 Jane 是管理员,因此她可以执行管理员的任务,而 John 只是作者:

Yii2编程:安全性

Yii 实现了所谓的“通用分层 RBAC,遵循 NIST RBAC 模型”。 RBAC 功能由其 authManager 应用程序组件提供。

我不会在这里深入探讨 RBAC,但我希望在以后的教程中能够深入探讨。再说一次,这取决于编辑女神——与她们交谈绝非易事:

Yii2编程:安全性

基本上,要彻底实施 RBAC,您必须:

  • 定义角色和权限
  • 建立您的角色和权限之间的关系
  • 定义任何现有的规则
  • 将规则与您的角色和权限相关联
  • 最后,为用户分配角色

您可以在下面看到启用 RBAC 系统所需的代码:

'
<?php
namespace appcommands;

use Yii;
use yiiconsoleController;

class RbacController extends Controller
{
    public function actionInit()
    {
        $auth = Yii::$app->authManager;

        // add "createPost" permission
        $createPost = $auth->createPermission('createPost');
        $createPost->description = 'Create a post';
        $auth->add($createPost);

        // add "updatePost" permission
        $updatePost = $auth->createPermission('updatePost');
        $updatePost->description = 'Update post';
        $auth->add($updatePost);

        // add "author" role and give this role the "createPost" permission
        $author = $auth->createRole('author');
        $auth->add($author);
        $auth->addChild($author, $createPost);

        // add "admin" role and give this role the "updatePost" permission
        // as well as the permissions of the "author" role
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $updatePost);
        $auth->addChild($admin, $author);

        // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
        // usually implemented in your User model.
        $auth->assign($author, 2);
        $auth->assign($admin, 1);
    }
}

要实现 RBAC,您必须准备好预先编写大量代码,或者随着应用程序的增长而编写大量代码。而且,如果您这样做,Yii 将根据您定义的身份验证框架来管理身份验证。换句话说,预先设计和编码可以提供可靠、详细的身份验证。

使用密码

正如马克·扎克伯格 (Mark Zuckerberg) 在 6 月份了解到的那样,一些网站以纯文本形式存储用户密码,但您的网站不应该这样做;公平地说,在密码管理器时代之前,我的 Facebook 帐户曾经因 PHPList 所做的事情而被黑客入侵过。不管怎样,Yii 使得加密和安全验证密码变得很容易。

Yii 的 crypt 函数使用 bcrypt 为您的密码生成哈希值。当人们注册时,会创建一个哈希值:

'
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);

然后,当用户尝试登录时,它会被散列并与数据库中的散列进行比较:

'
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
    // all good, logging user in
} else {
    // wrong password
}

但是您也可以使用 Yii 通过加密来保护数据。

密码学

Yii 框架提供了许多内置功能来支持数据保护:

  • 密码和密钥生成函数,例如generateRandomKey、generateRandomString 和generateSalt。
  • 密码验证:generatePasswordHash() 和 validatePassword()。
  • 加密/解密:encryptByKey()、decryptByKey()、encryptByPassword() 和 decryptByPassword()。
  • 使用标准算法派生密钥:pbkdf2() 和 hkdf()。
  • 防止数据篡改:hashData() 和 validateData()。

查看安全性

来自用户的任何数据都可能受到 SQL 注入或跨浏览器脚本等攻击的感染。重要的是,您在视图中输出给用户的任何数据都应该被清理。 Yii 为此提供了几种方法。

首先,有 Html::encode,它基本上破坏了任何 SQL 或脚本:

'
<?php
use yiihelpersHtml;
?>

<div class="username">
    <?= Html::encode($user->name) ?>
</div>

并且与 HtmlPurifier 库集成以实现更大的文本块:

'
<?php
use yiihelpersHtmlPurifier;
?>

<div class="post">
    <?= HtmlPurifier::process($post->text) ?>
</div>

通过身份验证客户端登录

Yii 还提供了第三方身份验证的功能,这对于支持通过 Google、Facebook、Twitter 等进行社交登录尤其有用。

我为 Envato Tuts+ 编写了几篇关于在 Yii 框架内使用 AuthClient 进行社交登录的教程:

  • 构建您的初创公司:使用 AuthClient 简化入口(待发布
  • 如何使用 Yii2 进行编程:Google 身份验证
  • 如何使用 Yii2 进行编程:AuthClient 与 Twitter、Google 和其他网络集成

我发现社交登录对于会议策划者来说效果非常好。新用户无需密码即可开始安排会议。

最佳实践

Yii 还推荐了一些 Web 应用程序安全方面的最佳实践。它的文档为任何人提供了有关这些主题的良好入门知识。

  1. 过滤输入和输出
  2. 避免 SQL 注入
  3. 避免跨站脚本 (XSS)
  4. 避免跨站请求伪造 (CSRF)
  5. 避免文件泄露
  6. 在生产中避免调试信息和工具
  7. 使用通过 TLS 的安全连接

上面的前三个主题可以通过上面视图安全中讨论的编码得到很好的管理。

Yii 还为常见活动提供内置的 CSRF 保护,并且可以在需要时将其关闭。在 Meeting Planner 中,我必须关闭 CSRF 才能接受从 Mailgun 的 API 服务发布的消息。

对于文件暴露,该框架通过将所有输入请求集中到 web/index.php 请求文件中来帮助最大限度地减少这种情况。这极大地限制了编写过滤请求的应用程序代码的需要。它在一个地方管理得很好。

最后,使用 HTTPS 可以帮助保护您的连接并与 Yii 一起保护用户。今年早些时候,我写了一篇有关 Let's Encrypt 的文章 — 您也可以使用本教程为 Yii 应用程序安装 HTTPS。

想了解更多内容吗?

如果您有兴趣阅读有关这些主题的更详细材料,Yii 1.x 框架提供了这些帖子。当然,它们比较旧,并且对 Yii 2 不太具体,但它们仍然有用。

  • 专题:安全
  • 如何编写安全的 Yii 应用程序
  • Yii 安全扩展指南

结束中

我希望您喜欢我对 Yii2 的安全性概述。如果您将上述大部分或全部概念的各个方面集成到您的应用程序中,您应该拥有一个基本安全的 Web 服务。您可能需要查看我们的“使用 PHP 构建您的初创公司”系列,了解其中一些安全实践的实际实施情况。

请观看我们的“使用 Yii2 编程”系列中即将推出的教程,我们将继续深入了解该框架的不同方面。我欢迎功能和主题请求。您可以将它们发布在下面的评论中,或者在我的 Lookahead Consulting 网站上向我发送电子邮件。

如果您想知道下一个 Yii2 教程何时发布,请在 Twitter 上关注我@reifman 或查看我的讲师页面。我的讲师页面将立即包含本系列的所有文章。

让我们共同努力,让编辑女神们开心。

相关链接

  • Yii 最佳安全实践
  • Yii 基础安全类
  • Yii2 开发者交流会
卓越飞翔博客
上一篇: 中地球轨道卫星
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏