If you're asking "What is Yii?" check out the Yii Framework Introduction, which reviews the benefits of Yii and includes an overview of Yii 2.0.
In this Programming with Yii2 series, I will guide readers in using the Yii2 PHP framework. If you plan to share your app with the public, it needs to be secure, and it's best to plan for this from the start. Luckily, starting with a framework like Yii makes this much easier than other frameworks. As stated in Yii Features:
Yii comes with many security measures to help protect your web applications from attacks such as SQL injection, cross-site scripting (XSS), cross-site request forgery (CSRF), and cookie tampering.
In this tutorial, I will walk you through basic security concepts within the Yii application framework. And, if you're interested, as the meeting planner app in our launch series nears alpha, future episodes will be dedicated to keeping the app secure.
Before we begin, please keep in mind that I do try to engage in the discussion below. If you have questions or topic suggestions, please leave a comment below or contact me on Twitter @reifman.
Note: If you notice there are gaps between episodes of the "Programming Yii" series, it's because I had to have brain surgery last year. Thank you for your patience and support - it's great to be writing regularly again and I look forward to continuing to cover Yii2.
If you are new to web application security, there is a lot to know about Yii's products. I'll try to provide an overview based on the best Yii 2.0 documentation. The Yii team divides security into seven key areas:
Let’s start digging into these one by one.
Ilko Kacharov's Yii Framework Security Demo provides some useful slides summarizing the goals of authentication (and the following subtopic, authorization). Essentially, here are the questions these topics need to answer:
Yii's yii/web/User class integrates with yii\web\IdentityInterface to manage the authentication state of users in your application.
Last November, I wrote a tutorial on Yii Advanced Application Templates. One of the advantages of the premium template is that it provides pre-built integration of the User model with ActiveRecord and databases. Therefore, your application immediately provides database-driven authentication.
The user model allows you to programmatically log in and out users:
$isGuest property determines whether the current user is logged in. It is null when the user logs out, but otherwise returns an instance of IdentityInterface.
Essentially, you need a User class that extends ActiveRecord and implements methods that support IdentityInterface, like this:
<?php use yii\db\ActiveRecord; use yii\web\IdentityInterface; 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; } }
Additionally, before creating a user, the application generates a random string as the authorization key. This can be used in "forgot password" emails or other email-based login links:
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 provides two built-in authorization methods. Simpler access control lists (ACLs) determine which users or processes are allowed to perform operations on a resource, while more intensive role-based access controls (RBAC) help you manage access by defining roles. In RBAC, only users or system tasks with specific roles can perform specific operations.
ACLs are sometimes called access control filters (ACF). Yii provides ACL support in yii\filters\AccessControl. It is ideal for applications that require only simple access control. Here's what I've used so far in Meeting Planner.
The following is an example of a common SiteController that configures access behavior to filter access to available actions (usually pages). In this example, the ACLs apply to registration, login, and logout. '?'
means that any user can access the login and registration pages, while '@'
means that access is only allowed to logged in or authenticated users. In the following example, only logged in users can log out:
use yii\web\Controller; use yii\filters\AccessControl; 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 只是作者:
Yii 实现了所谓的“通用分层 RBAC,遵循 NIST RBAC 模型”。 RBAC 功能由其 authManager 应用程序组件提供。
我不会在这里深入探讨 RBAC,但我希望在以后的教程中能够深入探讨。再说一次,这取决于编辑女神——与她们交谈绝非易事:
基本上,要彻底实施 RBAC,您必须:
您可以在下面看到启用 RBAC 系统所需的代码:
<?php namespace app\commands; use Yii; use yii\console\Controller; 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 框架提供了许多内置功能来支持数据保护:
来自用户的任何数据都可能受到 SQL 注入或跨浏览器脚本等攻击的感染。重要的是,您在视图中输出给用户的任何数据都应该被清理。 Yii 为此提供了几种方法。
首先,有 Html::encode
,它基本上破坏了任何 SQL 或脚本:
<?php use yii\helpers\Html; ?> <div class="username"> <?= Html::encode($user->name) ?> </div>
并且与 HtmlPurifier 库集成以实现更大的文本块:
<?php use yii\helpers\HtmlPurifier; ?> <div class="post"> <?= HtmlPurifier::process($post->text) ?> </div>
Yii 还提供了第三方身份验证的功能,这对于支持通过 Google、Facebook、Twitter 等进行社交登录尤其有用。
我为 Envato Tuts+ 编写了几篇关于在 Yii 框架内使用 AuthClient 进行社交登录的教程:
我发现社交登录对于会议策划者来说效果非常好。新用户无需密码即可开始安排会议。
Yii 还推荐了一些 Web 应用程序安全方面的最佳实践。它的文档为任何人提供了有关这些主题的良好入门知识。
上面的前三个主题可以通过上面视图安全中讨论的编码得到很好的管理。
Yii also provides built-in CSRF protection for common activities and can be turned off when needed. In Meeting Planner, I have to turn off CSRF to accept messages published from Mailgun's API service.
For file exposure, the framework helps minimize this by centralizing all incoming requests into the web/index.php request file. This greatly limits the need to write application code that filters requests. It's well managed in one place.
Finally, using HTTPS can help secure your connection and protect users with Yii. Earlier this year, I wrote an article about Let's Encrypt — you can also use this tutorial to install HTTPS for your Yii applications.
If you are interested in reading more detailed material on these topics, the Yii 1.x framework provides these posts. Sure, they're older and less specific to Yii 2, but they're still useful.
I hope you enjoyed my overview of Yii2 security. If you integrate aspects of most or all of the above concepts into your application, you should have a basically secure web service. You might want to check out our Building Your Startup with PHP series to see some of these security practices in action.
Check out the upcoming tutorials in our "Programming with Yii2" series as we continue to dive into different aspects of the framework. I welcome feature and theme requests. You can post them in the comments below or send me an email on my Lookahead Consulting website.
If you would like to know when the next Yii2 tutorial is released, follow me on Twitter @reifman or check out my instructor page. My instructor page will immediately contain all articles from this series.
Let us work together to make the editorial goddesses happy.
The above is the detailed content of Yii2 Programming: Security. For more information, please follow other related articles on the PHP Chinese website!