企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 权限验证 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并在配置文件中配置了用户名和密码,因为这是一个非常简单的方法,我们目前不需要更多的用户。 我们还确保了所有必需的操作和表单,以便只有已登录的用户可以添加新帖子或编辑现有帖子。