我有一个通常适用于我的登录脚本,但在检查存储用于登录的cookie后,偶尔会在重定向时进入无限循环。浏览器将报告如下内容:“Firefox检测到服务器正在以永远无法完成的方式重定向此地址的请求。”其他人也报告了这个问题。以下是登录过程的关键元素。我想知道是否有人可以看到这个过程/脚本的问题。
谢谢,
尼克
首先在受保护的每页顶部:
<?php
session_start();
$_SESSION['url'] = $_SERVER['REQUEST_URI'];
require('login/config.php');
require('login/functions.php');
if (allow_access(Users) != "yes")
{
include ('login/check_login.php');
exit;
}
?>
然后在 check_login.php :
<?
session_start();
//check to see if the user already has an open session
if (($_SESSION[user_name] != "") && ($_SESSION[password] != ""))
{
header("Location:$_SESSION[redirect]");
exit;
}
$lr_user = $_COOKIE['lr_user'];
$lr_pass = $_COOKIE['lr_pass'];
//check to see if cookies have been set previously
if(($lr_user != "") && ($lr_pass != ""))
{
header("Location:/login/redirect.php");
exit;
}
//if neither is true, redirect to login
header("Location:/login/login.php");
?>
然后,在 redirect.php:
中<?
session_start();
//require the functions file
require ("config.php");
require ("functions.php");
$lr_user = $_COOKIE['lr_user'];
$lr_pass = $_COOKIE['lr_pass'];
//check to see if cookies are already set, remember me
if ((!$lr_user) || (!$lr_pass))
{
$username = $_POST[username];
$password = $_POST[password];
}else{
$username = $lr_user;
$password = $lr_pass;
}
//sets cookies to remember this computer if the user asks to
if ($_POST[remember] == "Yes")
{
setcookie("lr_user", $username, $duration, "/", $domain);
setcookie("lr_pass", $password, $duration, "/", $domain);
}
//sets session variables
sess_vars($base_dir, $server, $dbusername, $dbpassword, $db_name, $table_name, $username, $password);
if(isset($_SESSION['url']))
$_SESSION[redirect] = $_SESSION['url']; // holds url for last page visited.
else
$_SESSION[redirect] = "/index.php"; // default page for
//redirects the user
header("Location:$_SESSION[redirect]");
?>
的functions.php
<?php
//function to get the date
function last_login()
{
$date = gmdate("Y-m-d");
return $date;
}
//function that sets the session variable
function sess_vars($base_dir, $server, $dbusername, $dbpassword, $db_name, $table_name, $username, $password)
{
//make connection to dbase
$connection = @mysql_connect($server, $dbusername, $dbpassword)
or die(mysql_error());
$db = @mysql_select_db($db_name,$connection)
or die(mysql_error());
$sql = "SELECT * FROM $table_name WHERE username = '$username' and password = password('$password')";
$result = @mysql_query($sql, $connection) or die(mysql_error());
//get the number of rows in the result set
$num = mysql_num_rows($result);
//set session variables if there is a match
if ($num != 0)
{
while ($sql = mysql_fetch_object($result))
{
$_SESSION[first_name] = $sql -> firstname;
$_SESSION[last_name] = $sql -> lastname;
$_SESSION[user_name] = $sql -> username;
$_SESSION[password] = $sql -> password;
$_SESSION[group1] = $sql -> group1;
$_SESSION[group2] = $sql -> group2;
$_SESSION[group3] = $sql -> group3;
$_SESSION[pchange] = $sql -> pchange;
$_SESSION[email] = $sql -> email;
$_SESSION[redirect] = $sql -> redirect;
$_SESSION[verified] = $sql -> verified;
$_SESSION[last_login] = $sql -> last_login;
}
}else{
$_SESSION[redirect] = "$base_dir/errorlogin.php";
}
}
//functions that will determine if access is allowed
function allow_access($group)
{
if ($_SESSION[group1] == "$group" || $_SESSION[group2] == "$group" || $_SESSION[group3] == "$group" ||
$_SESSION[group1] == "Administrators" || $_SESSION[group2] == "Administrators" || $_SESSION[group3] == "Administrators" ||
$_SESSION[user_name] == "$group")
{
$allowed = "yes";
}else{
$allowed = "no";
}
return $allowed;
}
//function to check the length of the requested password
function password_check($min_pass, $max_pass, $pass)
{
$valid = "yes";
if ($min_pass > strlen($pass) || $max_pass < strlen($pass))
{
$valid = "no";
}
return $valid;
}
?>
的config.php
<?
//set up the names of the database and table
$db_name ="";
$table_name ="authorize";
//connect to the server and select the database
$server = "localhost";
$dbusername = "";
$dbpassword = "*";
//domain information
$domain = "";
//Change to "0" to turn off the login log
$log_login = "1";
//base_dir is the location of the files, ie http://www.yourdomain/login
$base_dir = "";
//length of time the cookie is good for - 7 is the days and 24 is the hours
//if you would like the time to be short, say 1 hour, change to 60*60*1
$duration = time()+60*60*24*365*10;
//the site administrator\'s email address
$adminemail = "";
//sets the time to EST
$zone=3600*00;
//do you want the verify the new user through email if the user registers themselves?
//yes = "0" : no = "1"
$verify = "0";
//default redirect, this is the URL that all self-registered users will be redirected to
$default_url = "";
//minimum and maximum password lengths
$min_pass = 8;
$max_pass = 15;
$num_groups = 0+2;
$group_array = array("Users","Administrators");
?>
答案 0 :(得分:6)
编辑 - 试试这个:
我认为问题在于我认为你正在努力保护所有人。页面还包括index.php。但是,您已将index.php作为$ _SESSION [redirect]变量中的页面包含在内。你应该按照以下思路思考:
即使允许他们查看页面(导致循环问题),您的脚本仍会尝试重定向它们。
这是一个微妙的区别,但却是一个重要的区别(特别是当你保护所有页面时)。
在受保护网页的顶部,将底部代码段更改为:
if (allow_access(Users) != "yes")
{
include ('login/check_login.php');
check_redirect();
}
在check_login.php中试试这个:
<?
session_start();
function check_redirect()
{
//check to see if the user already has an open session
if (($_SESSION[user_name] != "") && ($_SESSION[password] != ""))
{
// just return if they are a valid user (no need to redirect them)
return;
}
$lr_user = $_COOKIE['lr_user'];
$lr_pass = $_COOKIE['lr_pass'];
//check to see if cookies have been set previously
if(($lr_user != "") && ($lr_pass != ""))
{
// just return if they are a valid user (no need to redirect them)
return;
}
//if neither is true, redirect to login
header("Location:/login/login.php");
die();
}
?>
你的redirect.php不需要soley保护你的页面,我假设你用你的实际login.php脚本,因此:
$_SESSION['url']
会存储他们试图访问的页面,并且您的redirect.php / login.php脚本应该在成功登录后使用它来重定向它们。
最后上面是未经测试的代码,但应该比你的工作更好,让我知道你是如何进行的。
说实话,很难确定你的代码究竟出了什么问题,因为还有一些未知变量,例如配置和函数文件以及函数:
if (allow_access(Users) != "yes")
我认为用户应该是&#39;用户&#39;同样,除非它只是为这个问题松散地输入你所有的变量,如$ _SESSION [user_name]你必须确保你正确添加撇号或你会得到所有地方的通知(未定义的变量,假设等等),不要太提及这会弄乱你的会话数据。
也许如果我就您当前的代码提出一些建议,您可以尝试一些可以修复代码的事情。
我首先要重写你的check_login.php和redirect.php脚本 - 事实上你有两个独立的脚本(可以合并)总会在某个阶段给你带来问题,因为基本上你是重定向到一个重定向(当你大声说出来的时候,它并不合乎逻辑。因此,首先将脚本重写为“auth.php&#39;脚本。并且还简化了包含需要身份验证的页面的内容,例如:
<?php
session_start();
// use require_once for your login scripts, not 'include' as you want an error to
// occur to halt the page processing if the file is not found, include will just
// give a warning but still continue with the page processing (which you're trying
// to protect). Lastly '_once' so you don't get multiple inclusions of the same
// script by accident (which is always import for login / redirect scripts).
require_once('login/auth.php');
// just create one function which will proxy all the other functions / includes
// you could exclude this function and just use the require_once file for direct
// access - but I would say including a function will make it easier to understand.
check_login();
?>
现在是auth.php文件:
<?php
session_start();
// if these are required use the _once. I would guess some of these 'functions'
// may be able to be included within this 'auth.php' file directly?
require_once('login/config.php');
require_once('login/functions.php');
// set your variables here
$_SESSION['url'] = $_SERVER['REQUEST_URI'];
// the main check login function
function check_login()
{
// Check if your user is logged in / needs to be logged in
// perhaps something from your allow_access() function?
// Do all the checks for session / cookie you should resolve the checks to
// a simple bool variable (i.e. if the user is valid or not)
$userIsValid = true || false; // get this from above code
// Then use the redirect function and pass in the $userIsValid variable
// which will tell the redirect() function where to redirect to.
redirect($userIsValid);
}
// use a separate function for the redirect to keep it cleaner
// not too sure on all the Url's you have floating around in your code as I
// would think you either want to let them to proceed to the page they were
// trying to view (if validated) or you want them to login?
function redirect($validUser = false)
{
// if the user is valid, just return as you don't have to redirect them
if ( $validUser ) {
return true;
}
// otherwise just redirect them to the login page
header("Location:/login/login.php");
die();
}
?>
您不需要(并且不应该!)将实际密码存储在会话中,我当然也建议不要使用cookie。但是,如果您必须将密码/用户名存储在cookie中,至少必须使用带有盐等的md5()加密它。所以简而言之,而不是检查$ _SESSION [&#39; user_name&#39;]和$ _SESSION [&#39;密码&#39;]它可能就像:
// if the user has no valid session do something:
if ( !isset($_SESSION['id']) ) {
}
我不确定你为什么要这样做:
$username = $_POST[username];
$password = $_POST[password];
在redirect.php文件中,您是否也在用户登录时使用此脚本?我不认为如果你是一个好主意(这可能是问题)。您应该有一个单独的脚本来处理所有实际的登录功能(包括登录后的重定向)。以上内容只应考虑:a)检查用户是否有效/登录b)重定向,如果没有 - 基本上保护您的网页。
您的代码:
//check to see if the user already has an open session
if (($_SESSION[user_name] != "") && ($_SESSION[password] != ""))
{
header("Location:$_SESSION[redirect]");
exit;
}
我不确定我是否在上下文中得到了这一点,因为如果他们有一个有效的会话,你基本上会重定向它们?我不太了解整个check_login.php脚本,因为事情有些倒退(特别是与redirect.php脚本结合使用时)。您正在再次检查相同的变量($ lr_user)|| (!$ lr_pass)在您的重定向脚本中,并引用了一些甚至未在check_login.php脚本中设置的内容。
编辑:可以解决方案吗? 除非我看过上面的代码块引用$ _SESSION [&#39; redirect&#39;],否则我认为应该是$ _SESSION [&#39; url&#39;]或者只是不要重定向他们。 $ _SESSION [&#39;重定向&#39;]在redirect.php脚本(如果会话存在时可能无法调用)之前不会被设置。
很抱歉,如果您没有像您希望的那样真正回答您的问题,但我认为这是一个很好的机会,可以好好看看您的脚本并清理/简化它们。理想情况下,您应该使用OOP方法来查看它,即创建会话,重定向,登录类。但如果坚持使用普通函数(程序),请确保为每个脚本创建一个干净的分隔。简而言之:
希望以上内容有道理,但如果没有,请告诉我。
答案 1 :(得分:0)
如果您真的想使用此代码,我认为这就是答案:
对于已禁用Cookie(隐私浏览)的用户,由于 check_login.php 中的行,所有用户都会卡住。因为这些值永远不会设置,会落入 check_login.php - &gt;的循环中。 login.php - &gt;的 check_login.php 强>:
$lr_user = $_COOKIE['lr_user'];
$lr_pass = $_COOKIE['lr_pass'];
//check to see if cookies have been set previously
if(($lr_user != "") && ($lr_pass != ""))
{
header("Location:/login/redirect.php");
exit;
}
//if neither is true, redirect to login
header("Location:/login/login.php");
Bur我真的建议你使用一些readily available会话管理片段。
我看到的问题,快速看一下:
a)正如史蒂夫所说,你不能在cookie中保存用户名和密码 EVER。您只保存随机会话ID值。
setcookie("lr_user", $username, $duration, "/", $domain);
setcookie("lr_pass", $password, $duration, "/", $domain);
b)您的 functions.php 受SQL injection约束。
$sql = "SELECT * FROM $table_name WHERE username = '$username' and
password = password('$password')";
c)用户输入永远不会被转义。
$username = $_POST[username];
$password = $_POST[password];
d)您在整个代码中拆分了会话管理检查。