【发布时间】:2016-01-15 09:21:16
【问题描述】:
所以,我想要达到的目标如下: 当您进入网站时,只有一个密码框。如果您输入与数据库中的密码匹配的密码,则会打开一个包含更多信息的弹出窗口。我该怎么做呢?
【问题讨论】:
-
您使用的是什么网络服务器/应用程序?
所以,我想要达到的目标如下: 当您进入网站时,只有一个密码框。如果您输入与数据库中的密码匹配的密码,则会打开一个包含更多信息的弹出窗口。我该怎么做呢?
【问题讨论】:
让我们分解你的问题:
网站登录比这更多,但这只是您问题的一般细分。
以下是我将在示例中为您使用的内容: - 我将 PHP 用于动态服务器端脚本 - 我将为 AJAX 登录请求使用一些 JavaScript(只是 vanilla JS,而不是 jQuery 或其他变体)。 显然你可以在你的实现中随意使用其他东西。
我将首先创建index.html,如下所示:
<!DOCTYPE html>
<html lang="en"> <!-- Assuming the language is English -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Some Snazzy Title for Login Page</title>
<script type="text/javascript" src="resources/js/functions.js"></script>
<!-- Any additional things you want to include in the head of the HTML page -->
</head>
<body>
<!-- Table is used here for formatting -->
<table id="LoginTable" style="margin-left:auto;margin-right:auto;">
<tr>
<td>Username:</td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="password" id="password"></td>
</tr>
</table>
<br>
<!--- Button to call our JavaScript AJAX login function: -->
<button onclick="AttemptLogin();">Login</button>
<!--- Include links to things like register, forgot password, and etc. here -->
</body>
</html>
您会注意到,我们包含一个名为 functions.js 的外部 JavaScript 文件,该文件位于 resources/js/ 子目录中。因此,要包含此内容,您将在与 index.html 相同的目录中创建一个名为 resources 的文件夹,然后在 内创建一个名为 js 的文件夹资源 文件夹。完成之后,我们就可以创建functions.js了:
/* Credits to Minko Gechev (blog.mgechev.com) for createXMLHttp() (I have made my own modifications to it, though.) */
function createXMLHttp(){
//If XMLHttpRequest is available then using it
if (typeof XMLHttpRequest !== undefined) {
// XMLHttpRequest is a fairly standard class in most browsers for handling AJAX, but
// it's not defined in all browsers (including IE)
return new XMLHttpRequest;
} else if (window.ActiveXObject) {
// User is using Internet Explorer
// Now we'll try to use an array of various IE XML HTTP types to find the right one:
var ieXMLHttpVersions = ['Microsoft.XMLHTTP', 'MSXML2.XMLHttp.5.0', 'MSXML2.XMLHttp.4.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp', 'Microsoft.XMLHttp'];
var xmlHttp;
// Look through the array and try to create the XMLHttp object
for (var i = 0; i < ieXMLHttpVersions.length; i++) {
try {
xmlHttp = new ActiveXObject(ieXMLHttpVersions[i]);
return xmlHttp;
} catch (e) {
// Do nothing with error
}
}
// Despite the fact that ActiveXObject is defined, none of the XMLHttp versions could be
// successfully created. The browser's JavaScript implementation is unknown and thus we cannot
// use AJAX for this.
return null;
}else{
// This browser is unknown and it does not support any of the common XML HTTP classes.
// As such, we will not be able to AJAX for login through this.
return null;
}
}
function AttemptLogin(){
// First we'll get the current timestamp which we'll append to the login link to prevent caching:
var timestamp = new Date().getTime();
// Link to POST login data to (with cache-buster):
var url = "ajax/login_process.php?cachebuster=" + timestamp;
var username = encodeURIComponent(document.getElementById("username").value);
var password = encodeURIComponent(document.getElementById("password").value);
var PostRequestData = "u=" + username + "&p=" password";
var xmlHttp = createXMLHttp();
if(xmlHttp === null){
// xmlHttp could not be successfully created
// Alert the user of this issue and recommend a browser upgrade
alert("An error occurred that prevented us from logging in.\nThis issue seems to have been caused by your browsers JavaScript implementation. Please consider updating your browser to the newest version or installing a different browser.");
// Exit the function prematurely
return;
} // Else, xmlHttp appears to have been created successfully
xmlHttp.open('POST', url, true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Code the callback function which will be executed after the request completes.
xmlHttp.onreadystatechange = function(){
if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){
// It seems like the request successfully executed
// Now we'll just need to check if the login was successful or not:
var respText = xmlHttp.responseText;
if(respText.indexOf("login success") > -1){
// Now we'll open a popup window here:
window.open('info.phtml', 'More Information', 'height=400,width=400');
// Info.phtml will do additional security checks before displaying the information, by the way.
}else{
alert("Error: either the username does not exist or the is incorrect for the username provided.\nPlease try again.");
}
}
}
// Now that we have the request open, the request header is set, and the callback
// function is defined, we will finally send the actual login request to the login_process.php page:
xmlHttp.send(PostRequestData);
}
现在我们需要写出login_process.php 的代码。不过,在此之前,我们需要创建此文件的目录。因此,在您放置index.html 文件的同一个文件夹中,您应该创建一个名为ajax 的子目录。现在我们将写入该文件夹中的login_process.php 文件:
<?php
// Start up a session so we can hold whether the user is logged in or not:
session_start();
// To further prevent caching we'll use these headers:
header("Cache-control: no-store, no-cache, must-revalidate");
header("Expires: " . gmdate("D, d M Y H:i:s", (time() + 2)) . " GMT");
header("Date: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Pragma: no-cache");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// Make sure the request is valid:
if($_SERVER['REQUEST_METHOD'] != 'POST'){
die("Invalid request type");
}
// Now let's do the login.
// First, connect to the database:
$mysqli = new mysqli("Your database host", "Your database username", "Your database password", "The database name");
if($mysqli->connect_errno){
die("Failed to connect to database");
}
// Next we'll get the request parameters
$username = $_POST['u'];
$password = $_POST['p'];
// Now we need to clean the username so we can search the database for it
$safeUsername = $mysqli->real_escape_string($username); // Prevents SQL injection
// Next let's query to see if this username exists:
$result = $mysqli->query("SELECT * FROM `TableName` WHERE `username`='$safeUsername' LIMIT 1;");
if($result->num_rows == 0){
// The username is unknown.
// Close the database members and die with vague error message
$result->free();
$mysqli->close();
die("fail");
} // Else, username exists
// Get this user's salts and password hash:
$row = $result->fetch_assoc();
// Now that we have the results as a PHP keyed array, we do not need to keep
// the database open any longer. So we will now close the database connection and
// free the database-related objects from the memory.
$result->free();
$mysqli->close();
// Now pull out the database provided values to local variables (for convenience):
$passwordSalt_1 = $row['salt1'];
$passwordSalt_2 = $row['salt2'];
$passwordHash = strtolower($row['passHash']); // Hexdigest of users current password hash
// Hash the users password with the salt and see if the results match:
$userPasswordData = $passwordSalt_1 . $password . $passwordSalt_2;
$requestedPassHash = strtolower(hash('sha512', $userPasswordData));
// Now we just need to see if the user's passHash in the database is the same as
// the hash we just generated via the password sent in the request:
$isLoggedIn = ($passwordHash == $requestedPassHash);
$_SESSION['logged_in'] = ($isLoggedIn ? '1' : '0');
// Send back the login result to the AJAX callback function:
die(($isLoggedIn ? "login success" : 'fail'));
?>
现在我们剩下的就是编码info.phtml(弹出网页):
<?php
// Start up the session so we can access the session variables:
session_start();
// We certainly don't want the browser to cache our webpage which should require login:
header("Cache-control: no-store, no-cache, must-revalidate");
header("Expires: " . gmdate("D, d M Y H:i:s", (time() + 2)) . " GMT");
header("Date: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Pragma: no-cache");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// Now we'll simply check if the user is logged in by referencing the session:
if( !isset($_SESSION['logged_in']) || // Check if session variable is set
empty($_SESSION['logged_in']) || // Check if the variable isn't empty
($_SESSION['logged_in'] != '1') ){ // Check if the variable is anything other than the valid value
// If any of the above statements are true, we reach this code and the user is not properly logged in
// As such, we should display an error page message instead of displaying the page.
header($_SERVER["SERVER_PROTOCOL"] . " 418 I'm a teapot", true, 418);
/* Personal Note: I'm using 418 'I'm a teapot' here out of personal preference.
Technically the RFC has not defined a response code for telling a user that they need
to login to the website before accessing the page, but sending back a non-4xx response
does not seem reasonable. 4xx response codes tell the client that there was an error
with their request. Since this wasn't a server a error and the request did not go over
successfully, a level 4xx response is the most fitting. */
die("Error: You need to login before accessing this page.");
} // Else, the user is logged in. Go ahead and show them the page.
?>
希望这可以帮助您设置您的网站。如果这确实有帮助,请不要忘记投票。 (不是试图乞求,但我确实花了很长时间写下你的问题的答案:P)我没有测试提供的代码,所以我确信整个过程中可能存在一些小错误。显然,您需要重写代码的某些部分以适应您的情况,但总的来说,它应该让您深入了解这种可以编码的系统。
【讨论】: