# 权限验证
Nette为您提供了如何在页面上对身份验证进行编程的指导,但不强迫您以任何特定方式进行验证。 实现取决于你。 Nette有一个Nette \ Security \ IAuthenticator接口,强制您只实现一个名为authenticate的方法,它找到用户无论你想要做什么。
有很多方式如何用户可以验证自己。 最常见的方法是基于密码的身份验证(用户提供其姓名或电子邮件和密码),但也有其他方法。 您可能熟悉许多网站上的“使用Facebook登录”按钮,或通过Google / Twitter / GitHub或任何其他网站登录。 有了Nette,你可以有任何你想要的验证方法,或者你可以组合它们。 随你便。
通常你会编写自己的认证器,但对于这个简单的小博客,我们可以使用SimpleAuthenticator,它与Nette捆绑在一起。 它提供基于密码的身份验证,用户名和密码存储在配置文件中。 在config.neon中添加安全部分(不要忘记更改密码):
~~~
security:
users:
admin: secret # user 'admin', password 'secret'
~~~
![](https://box.kancloud.cn/04951b66111616d945e5babab27cd5ab_763x484.png)
Nette将自动在DI容器中创建一个名为authenticator的服务。
# 登录表单
我们现在拥有身份验证的后端部分,我们需要提供一个用户界面,用户将通过它登录。让我们创建一个名为SignPresenter的新控制器,他主要功能有以下
1、显示登录表单(要求输入用户名和密码)
2、在表单提交时验证用户
3、提供注销操作。
让我们从登录表单开始。 你已经知道表单在控制器中如何工作。 创建SignPresenter控制器并增加一个方法createComponentSignInForm。 它应该看起来像这样:
~~~
<?php
namespace App\Presenters;
use Nette;
use Nette\Application\UI\Form;
class SignPresenter extends Nette\Application\UI\Presenter
{
protected function createComponentSignInForm()
{
$form = new Form;
$form->addText('username', 'Username:')
->setRequired('Please enter your username.');
$form->addPassword('password', 'Password:')
->setRequired('Please enter your password.');
$form->addSubmit('send', 'Sign in');
$form->onSuccess[] = [$this, 'signInFormSucceeded'];
return $form;
}
~~~
![](https://box.kancloud.cn/7c5acd123912cfb437e267371c458550_894x643.png)
现在有一个用户名和密码的输入表单了。
# 视图
表单将显示在模板app / presenters / templates / Sign / in.latte中
~~~
{block content}
<h1 n:block=title>Sign in</h1>
{control signInForm}
~~~
![](https://box.kancloud.cn/9dbb0df04a756ccff8ef455f52afc332_882x496.png)
# 登录处理程序
我们还添加了一个用于登录用户的表单处理程序,该表单处理程序在表单提交后立即调用。
处理程序将只接受用户输入的用户名和密码,并将其传递给之前定义的认证器。 用户登录后,我们会将他重定向到首页。我们现在在SignPresenter.php控制器中增加以下方法。
~~~
public function signInFormSucceeded($form, $values)
{
try {
$this->getUser()->login($values->username, $values->password);
$this->redirect('Homepage:');
} catch (Nette\Security\AuthenticationException $e) {
$form->addError('Nesprávné přihlašovací jméno nebo heslo.');
}
}
~~~
当用户名或密码与我们之前定义的不匹配时,User :: login()方法应该抛出异常。 正如我们已经知道的,这将导致Tracy的红屏,或者,在生产模式下,通知内部服务器错误的消息。 我们不会喜欢。 这就是为什么我们捕获异常,并添加一个漂亮和友好的错误消息到窗体。
当窗体中出现错误时,带有窗体的页面将被再次渲染,并且在窗体上方,会有一个很好的消息,通知用户他们输入了错误的用户名或密码。
# POST表单
首先,让我们保证创建新帖子的形式。 它在PostPresenter中定义并在app / presenters / templates / Post / create.latte中呈现。 我们的第一个目标是不允许用户在未登录的情况下查看该页面。
# 控制器视图
让我们创建一个动作方法actionCreate,它将用户重定向到登录形式,如果用户没有登录,需要验证。
~~~
public function actionCreate()
{
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
}
~~~
我们还应该保护编辑视图,所以只需添加那些三行。
~~~
public function actionEdit($postId)
{
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
~~~
![](https://box.kancloud.cn/1c59dd9808819bc378cb21e1d2a441fd_804x635.png)
# 隐藏链接
未经身份验证的用户看不到创建或编辑页面,但他仍然可以看到指向他们的链接。 让我们隐藏这些链接。 在app / presenters / templates / Homepage / default.latte中一个这样的链接,并且只有在用户登录时才可见。
我们可以使用名为n:if的n:标注隐藏它。 如果其中的语句为false,则将不显示整个<a>标记及其内容
~~~
<a n:href="Post:create" n:if="$user->loggedIn">Create post</a>
~~~
这是一个快捷方式(不要混淆标签if)
~~~
{if $user->loggedIn}<a n:href="Post:create">Create post</a>{/if}
~~~
您应该以类似的方式隐藏位于app / presenters / templates / Post / show.latte中的编辑链接。
# 表单处理程序
最后,最重要的是保护表单处理程序。 因为组件是可重用的,它们可以在几个视图中呈现。 因为它们可以在几个视图中渲染,它们也可以从任何这样的视图提交,甚至是不真正存在的视图。 这意味着,即使视图创建没有呈现,通过调整url,用户仍然可以提交表单(和添加/编辑帖子)。
它可以防止与一个简单的,我们将添加在postFormSucceeded的开始
~~~
public function postFormSucceeded($form)
{
if (!$this->getUser()->isLoggedIn()) {
$this->error('You need to log in to create or edit posts');
}
~~~
这很简单,但你永远不会忘记这样做,因为它是非常重要保护你的应用程序。
# 登录表单链接
嘿,但是我们怎么进入登录页面? 没有指向它的链接。 让我们在app/presenters/templates/@layout.latte模板文件中添加一个。
~~~
<ul class="navig">
<li><a n:href="Homepage:">Homepage</a></li>
{if $user->loggedIn}
<li><a n:href="Sign:out">Sign out</a></li>
{else}
<li><a n:href="Sign:in">Sign in</a></li>
{/if}
</ul>
~~~
如果用户尚未登录,我们将显示“登录”链接。 否则,我们将显示“退出”链接。 我们在SignPresenter中添加注销操作。
注销操作看起来像这样,并且因为我们立即重定向用户,所以不需要视图模板。
~~~
public function actionOut()
{
$this->getUser()->logout();
$this->flashMessage('You have been signed out.');
$this->redirect('Homepage:');
}
~~~
它只是调用logout()方法,然后向用户显示一个很好的消息。
有一个登录链接指向一个新的控制器,询问用户的凭据和验证他。 我们使用SimpleAuthenticator并在配置文件中配置了用户名和密码,因为这是一个非常简单的方法,我们目前不需要更多的用户。 我们还确保了所有必需的操作和表单,以便只有已登录的用户可以添加新帖子或编辑现有帖子。
- Nette简介
- 快速开始
- 入门
- 主页
- 显示文章详细页
- 文章评论
- 创建和编辑帖子
- 权限验证
- 程序员指南
- MVC应用程序和控制器
- URL路由
- Tracy - PHP调试器
- 调试器扩展
- 增强PHP语言
- HTTP请求和响应
- 数据库
- 数据库:ActiveRow
- 数据库和表
- Sessions
- 用户授权和权限
- 配置
- 依赖注入
- 获取依赖关系
- DI容器扩展
- 组件
- 字符串处理
- 数组处理
- HTML元素
- 使用URL
- 表单
- 验证器
- 模板
- AJAX & Snippets
- 发送电子邮件
- 图像操作
- 缓存
- 本土化
- Nette Tester - 单元测试
- 与Travis CI的持续集成
- 分页
- 自动加载
- 文件搜索:Finder
- 原子操作