| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| = 使用 PHP 创建数据库驱动的应用程序 |
| :jbake-type: tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :icons: font |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :description: 使用 PHP 创建数据库驱动的应用程序 - Apache NetBeans |
| :keywords: Apache NetBeans, Tutorials, 使用 PHP 创建数据库驱动的应用程序 |
| |
| = 第 5 课:添加安全功能。实现应用程序用户登录 |
| :jbake-type: tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :icons: font |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :description: 第 5 课:添加安全功能。实现应用程序用户登录 - Apache NetBeans |
| :keywords: Apache NetBeans, Tutorials, 第 5 课:添加安全功能。实现应用程序用户登录 |
| |
| |
| |
| 1. link:wish-list-tutorial-main-page.html[+使用 PHP 创建数据库驱动的应用程序 - 主页+] |
| 2. |
| 创建数据库 |
| |
| 1. link:wish-list-lesson1.html[+创建 MySQL 数据库+] |
| 2. link:wish-list-oracle-lesson1.html[+创建 Oracle 数据库表+] |
| 3. link:wish-list-lesson2.html[+设计应用程序。从数据库读取数据+] |
| 4. link:wish-list-lesson3.html[+创建新的应用程序用户+] |
| 5. link:wish-list-lesson4.html[+优化代码+] |
| 6. |
| *=> 添加安全功能。实现应用程序用户登录* |
| |
| 7. link:wish-list-lesson6.html[+在数据库中添加新的愿望+] |
| 8. link:wish-list-lesson7.html[+更新和删除数据库中的条目+] |
| 9. link:wish-list-lesson8.html[+使用 CSS 技术改进应用程序的外观+] |
| 10. link:wish-list-lesson9.html[+将应用程序部署到远程 Web 服务器+] |
| |
| image::images/netbeans-stamp-80-74-73.png[title="此页上的内容适用于 NetBeans IDE 7.2、7.3、7.4 和 8.0"] |
| |
| 在本课中,将为许愿者实现登录功能。这会影响以下文件: |
| |
| * ``index.php`` |
| * ``createNewWisher.php`` |
| * ``editWishlist.php`` |
| * ``db.php`` |
| |
| 实现登录功能包括以下步骤: |
| |
| 1. <<savingWisherIDInSessionUponCreation,在创建许愿者后,在会话中保存许愿者 ID>> |
| 2. <<validateWisherLogon,验证尝试编辑愿望列表的用户是否登录>> |
| 3. <<logonFromIndexPage,许愿者从 index.php 页中登录>> |
| |
| 当前文档是“在适用于 PHP 的 NetBeans IDE 中创建 CRUD 应用程序”教程的一部分。 |
| |
| |
| |
| == 来自上一课的应用程序源代码 |
| |
| MySQL 用户:单击link:https://netbeans.org/files/documents/4/1930/lesson4.zip[+此处+]以下载源代码,该代码反映了在完成上一课之后的项目状态。 |
| |
| Oracle 数据库用户:单击link:https://netbeans.org/projects/www/downloads/download/php%252Foracle-lesson4.zip[+此处+]以下载源代码,该代码反映了在完成上一课之后的项目状态。 |
| |
| |
| == 创建后在会话中保存许愿者 ID |
| |
| link:http://us2.php.net/manual/en/ref.session.php[+会话+]是持久性存储,可用于将信息从一个页面传输到另一个页面,而无需使用 link:wish-list-lesson5.html#htmlForm[+HTML 输入窗体+]。可通过预定义的 PHP 数组 ``$_SESSION`` 支持该功能。 |
| |
| 为安全起见,在创建新的许愿者后,该许愿者将自动登录而无需填写窗体。因此,您需要修改 ``createNewWisher.php`` 文件以实现以下功能: |
| |
| * 将新许愿者添加到数据库中。 |
| * 打开会话。 |
| * 在会话中存储许愿者的名字。 |
| * 在将许愿者重定向到 ``editWishList.php`` 页时,传输会话中的许愿者名字。 |
| |
| 在 ``createNewWisher.php`` 文件中,找到以下行: |
| |
| |
| [source,java] |
| ---- |
| |
| WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]); |
| ---- |
| |
| 然后,在其下输入以下代码块: |
| |
| |
| [source,java] |
| ---- |
| |
| session_start(); |
| $_SESSION['user'] = $_POST['user']; |
| ---- |
| |
| 该代码块启动一个会话,这意味着打开 ``$_SESSION`` 数组以输入或检索数据。然后,该代码在 ``$_SESSION`` 数组中添加一个元素。添加的元素包含一个值和标识符(键)。该值是新创建的许愿者名字,标识符是 "user"。然后,程序将许愿者重定向到 ``editWishList.php`` 页。 |
| |
| |
| == 验证用户登录 |
| |
| 当用户访问 ``editWishList.php`` 页时,应用程序应确认刚才在 ``createNewWisher.php`` 页上注册的同一个人访问了该页。 |
| |
| 实现该功能包括两个步骤: |
| |
| * <<retrievingUserNameFromSession,从会话中检索许愿者的名字>> |
| * <<redirectingNotLoggedInUserToIndexPage,如果从会话中检索许愿者名字失败,将用户重定向到 index.php>> |
| |
| |
| === 从会话中检索许愿者的名字 |
| |
| 将 ``editWishList.php`` 的 PHP 块中的默认代码替换为以下内容: |
| |
| [source,java] |
| ---- |
| |
| session_start(); |
| if (array_key_exists("user", $_SESSION)) { |
| echo "Hello " . $_SESSION['user']; |
| } |
| ---- |
| |
| 该代码块打开 ``$_SESSION`` 数组以检索数据,并验证 ``$_SESSION`` 是否包含具有 "user" 标识符的元素。如果检查成功,该代码将输出欢迎消息。 |
| |
| 检查是否正确实现会话: |
| |
| 1. 运行 ``createNewWisher.php`` 文件,然后创建一个新的许愿者,例如,Jack。 |
| ``editWishList.php`` 打开,并显示 Hello Jack。 |
| 2. 在浏览器中清除会话 Cookie,或者结束会话并从 IDE 中运行 ``editWishList.php`` 。 |
| ``editWishList.php`` 文件打开并显示 Hello,因为没有通过会话传输任何用户。这是不正确的,因为它允许未登录和未注册的人创建或编辑愿望列表。为了避免出现该问题,需要将用户重定向到 ``index.php`` 页。 |
| |
| |
| === 重定向未登录的用户 |
| |
| 将以下代码块添加到 ``editWishList.php`` 中的 ``if`` 子句之下: |
| |
| [source,java] |
| ---- |
| |
| else { |
| header('Location: index.php'); |
| exit; |
| } |
| ---- |
| |
| 该代码将用户重定向到 index.php 页并取消 PHP 代码执行。 |
| |
| 要检查是否正确实现了该功能,请运行 ``editWishList.php`` 文件。预期的结果是打开 ``index.php`` 页。 |
| |
| |
| == 从 index.php 页中登录 |
| |
| 从 index.php 页中登录包括两个步骤: |
| |
| * <<logonForm,在 HTML 输入窗体中输入用户的名字和口令,并将用于验证的数据提交到 index.php 页。>> |
| * <<logonValidation,验证登录>> |
| |
| |
| === 用于在 index.php 上登录的 HTML 窗体 |
| |
| 在 ``index.php`` 文件中,在结束 ``</body>`` 标记前输入以下代码: |
| |
| [source,xml] |
| ---- |
| |
| <form name="logon" action="index.php" method="POST" > |
| Username: <input type="text" name="user"> |
| Password <input type="password" name="userpassword"> |
| <input type="submit" value="Edit My Wish List"> |
| </form> |
| ---- |
| |
| *注:*您可以忽略来自 HTML 验证器的警告。 |
| |
| 该代码显示一个 link:wish-list-lesson3.html#htmlForm[+HTML 窗体+],用于在文本字段中输入用户的名字和口令。当用户单击 "Edit My Wish List" 时,数据将传输到同一页,即 index.php。 |
| |
| |
| === 登录验证 |
| |
| 登录验证包括: |
| |
| * <<checkWhereUserCameFrom,检查从中重定向用户的位置>>。 |
| * <<verifyCredentials,验证用户的名字和口令>>。 |
| * 将用户名保存到会话中并将用户重定向到 editWishList.php 页或<<displayErrorMessage,显示一条错误消息。>> |
| |
| 用户可以在启动应用程序时访问 ``index.php`` 页,从 <<validateWisherLogon,editWishList.php>> 页中进行访问,或者在输入名字和口令后从 ``index.php`` 页中重定向时访问该页。 |
| |
| 由于仅在最后一种情况下使用 link:http://www.htmlcodetutorial.com/forms/_FORM_METHOD.html[+HTML 请求方法+] POST,因此,您始终可以了解用户访问 ``index.php`` 时所在的位置。 |
| |
| 在 index.php 文件中,使用以下代码在 HTML 块上面创建一个 <?php ?> 块: |
| |
| [source,php] |
| ---- |
| |
| <?php |
| |
| require_once("Includes/db.php"); |
| $logonSuccess = false;// verify user's credentials |
| if ($_SERVER['REQUEST_METHOD'] == "POST") { |
| $logonSuccess = (WishDB::getInstance()->verify_wisher_credentials($_POST['user'], $_POST['userpassword'])); |
| if ($logonSuccess == true) { |
| session_start(); |
| $_SESSION['user'] = $_POST['user']; |
| header('Location: editWishList.php'); |
| exit; |
| } |
| } |
| ?> |
| |
| ---- |
| |
| 代码块顶部允许使用 ``db.php`` 文件,并使用 ``false`` 值初始化 ``$logonSuccess`` 变量。如果验证成功,该值将变为 ``true`` 。 |
| |
| 验证用户凭证的代码先检查请求方法是否为 POST。如果请求方法是 POST,则在提交<<logonForm,登录窗体>>后重定向用户。在这种情况下,代码块使用在登录窗体中输入的名字和口令调用 ``verify_wisher_credentials`` 函数。 |
| |
| ``verify_wisher_credentials`` 函数(在<<verifyWisherCredentials,下一节>>中编写)检查 ``wishers`` 表中是否存在用户和口令与<<logonForm,登录窗体>>中提交的值相匹配的记录。如果 ``verify_wisher_credentials`` 函数返回 ``true`` ,则在数据库中注册一个具有指定名字和口令组合的许愿者。这表示验证成功,并且 ``$logonSuccess`` 将值更改为 ``true`` 。在这种情况下,将启动一个会话并打开 ``$_SESSION`` 数组。该代码在 ``$_SESSION`` 数组中添加一个新元素。该元素包含一个值和标识符(键)。该值是许愿者的名字,标识符是 "user"。然后,该代码将用户重定向到 ``editWishList.php`` 页以编辑愿望列表。 |
| |
| 如果 ``verify_wisher_credentials`` 函数返回 ``false`` ,则 ``$logonSuccess`` 变量值保持为 false。将使用该变量值<<displayErrorMessage,显示错误消息>>。 |
| |
| |
| === verify_wisher_credentials 函数 |
| |
| 要实现验证许愿者凭证的功能,您需要在 ``db.php`` 文件的 ``WishDB`` 类中添加一个新函数。该函数要求将名字和口令作为输入参数,并返回 0 或 1。 |
| |
| *对于 MySQL 数据库*,请输入以下代码块: |
| |
| [source,java] |
| ---- |
| |
| public function verify_wisher_credentials ($name, $password){$name = $this->real_escape_string($name);$password = $this->real_escape_string($password);$result = $this->query("SELECT 1 FROM wishers |
| WHERE name = '" . $name . "' AND password = '" . $password . "'"); |
| return $result->data_seek(0); |
| } |
| ---- |
| |
| *对于 Oracle 数据库*,请输入以下代码块(由于 OCI8 没有等效的 ``mysql_num_rows`` ,该代码是 ``get_wisher_id_by_name`` 的修改形式): |
| |
| |
| [source,java] |
| ---- |
| |
| public function verify_wisher_credentials($name, $password) { |
| $query = "SELECT 1 FROM wishers WHERE name = :name_bv AND password = :pwd_bv"; |
| $stid = oci_parse($this->con, $query); |
| oci_bind_by_name($stid, ':name_bv', $name); |
| oci_bind_by_name($stid, ':pwd_bv', $password); |
| oci_execute($stid); |
| //Because name is a unique value I only expect one row |
| $row = oci_fetch_array($stid, OCI_ASSOC); |
| if ($row) |
| return true; |
| else |
| return false; |
| } |
| ---- |
| |
| 该代码块执行查询 ``"SELECT 1 FROM wishers WHERE Name = '" . $name . "'AND Password = '" . $password . "'"`` 并返回满足指定查询的记录数。如果找到此类记录,该函数将返回 ``true`` 。如果在数据库中找不到此类记录,该函数将返回 ``false`` 。 |
| |
| |
| === 显示错误消息 |
| |
| 要允许应用程序显示错误消息,请输入以下 <? php ?> 代码块(在 ``index.php`` 的登录窗体中的输入字段之下、按钮之上): |
| |
| [source,php] |
| ---- |
| |
| <?php |
| if ($_SERVER["REQUEST_METHOD"] == "POST") { |
| if (!$logonSuccess) |
| echo "Invalid name and/or password"; |
| } |
| ?> |
| ---- |
| 该代码块检查 $logonSuccess 变量值;如果该值为 false,则显示一条错误消息。 |
| |
| |
| == 测试从 index.php 页中登录 |
| |
| 检查登录功能在主页 ``index.php`` 上是否正常工作: |
| |
| 1. 运行应用程序。 |
| 2. 在 ``index.php`` 页上,在 "Username" 编辑框中输入 Tom,在 "Password" 编辑框中输入 Tim。 |
| 3. 按 "Edit My Wish List"。将显示一条错误消息(请注意,下面的浏览器窗口宽度减小为 600px,其中添加了一些换行符): |
| image::images/incorrectNamePasswordIndex.png[] |
| 4. 在 "Username" 编辑框中输入 Tom,在 "Password" 编辑框中输入 tomcat。 |
| 5. 按 "Edit My Wish list"。将显示 editWishList.php 页: |
| image::images/SuccessfulLogonOnIndexRedirectToEditWishList.png[] |
| |
| |
| == 完成当前课程后的应用程序源代码 |
| |
| MySQL 用户:单击link:https://netbeans.org/files/documents/4/1931/lesson5.zip[+此处+]以下载源代码,该代码反映了在完成课程后的项目状态。 |
| |
| Oracle 数据库用户:单击link:https://netbeans.org/projects/www/downloads/download/php%252Foracle-lesson5.zip[+此处+]以下载源代码,该代码反映了在完成课程后的项目状态。 |
| |
| |
| == 后续步骤 |
| |
| link:wish-list-lesson4.html[+<< 上一课+] |
| |
| link:wish-list-lesson6.html[+下一课 >>+] |
| |
| link:wish-list-tutorial-main-page.html[+返回到教程主页+] |
| |
| |
| link:/about/contact_form.html?to=3&subject=Feedback:%20PHP%20Wish%20List%20CRUD%205:%20Implementing%20Security[+发送有关此教程的反馈意见+] |
| |
| |
| 要发送意见和建议、获得支持以及随时了解 NetBeans IDE PHP 开发功能的最新开发情况,请link:../../../community/lists/top.html[+加入 users@php.netbeans.org 邮件列表+]。 |
| |
| link:../../trails/php.html[+返回至 PHP 学习资源+] |
| |