登录重定向时出现无限循环 [英] Infinite loop on login redirect

查看:889
本文介绍了登录重定向时出现无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通常对我有用的登录脚本,但是在检查存储的登录cookie后,有时会进入重定向的无限循环.浏览器将报告如下内容:"Firefox已检测到服务器正在以永远无法完成的方式重定向对该地址的请求."其他人也报告了此问题.以下是登录过程的关键元素.我想知道是否有人可以看到此过程/脚本出了什么问题.

I have a login script which generally works for me, but occasionally goes into an infinite loop on redirecting after checking the cookie stored for login. The browser will report something like the following: "Firefox has detected that the server is redirecting the request for this address in a way that will never complete." Others have reported this issue too. Below are the key elements of the login process. I wonder if someone can see what the issue is with this process/script.

谢谢

尼克

首先在受保护的每个页面的顶部:

First at the top of each page that is protected:

<?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");

?>

推荐答案

编辑-尝试以下操作:

我认为问题是我假设您正在尝试保护还包括index.php的所有"页面.但是,您已将index.php作为页面包含在$ _SESSION [redirect]变量中.您应该遵循以下思路:

I think the problem is that I assume you are trying to protect 'all' pages which also include the index.php. However you have included the index.php as a page in the $_SESSION[redirect] variable. You should think along the lines of:

  1. 用户尝试访问页面
  2. 您应该检查是否允许他们
  3. 如果允许,请让他们查看页面而不会受到干扰
  4. 如果没有登录(即未登录),请将其重定向到您的登录页面

即使允许他们查看页面,您的脚本仍在尝试重定向它们(这会导致循环问题).

Your script is trying to still redirect them even if they are allowed to view the page (which is causing the loop problem).

这是一个微妙的区别,但又是一个重要的区别(尤其是在保护所有页面的情况下).

It is a subtle difference, but an important one (especially as you are protecting all pages).

在受保护页面的顶部,将底部代码段更改为:

At the top of your protected pages change the bottom snippet to:

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,我假设您将其与实际的login.php脚本一起使用,因此:

Your redirect.php is not needed for soley protecting your pages, I assume you use this with your actual login.php script, therefore:

$_SESSION['url']

应该存储了他们要访问的页面,并且您的redirect.php/login.php脚本应该仅使用它在成功登录后将其重定向回那里.

Would have stored the page they were trying to get to, and your redirect.php / login.php script should just use this to redirect them back there after successful login.

最后,上面是未经测试的代码,但是应该比您拥有的更好,请让我知道您的工作方式.

Lastly the above is untested code but should work better than what you had, let me know how you get on.

说实话,要确定代码到底有什么问题是非常困难的,因为仍然存在一些未知变量,例如config和functions文件以及function:

To be honest it is quite hard to determine exactly what is wrong with your code because there are still a few unknown variables, such as the config and functions files and the function:

if (allow_access(Users) != "yes")

我假设Users应该是'Users',同样地,除非只是为这个问题松散地键入所有您具有$ _SESSION [user_name]之类的变量,则必须确保正确添加撇号,否则您会收到所有通知在该位置(未定义的变量,假定的...等)位置过分提及可能会破坏您的会话数据.

Which I assume Users should be 'Users', likewise unless it was just loosely typed for this question all the variables which you have like $_SESSION[user_name] you MUST make sure you correctly add the apostrophes or you will get notices all over the place (undefined variable, assumed...etc etc) not too mention this could mess up your session data.

也许如果我对您当前的代码提供了一些建议,您也许可以尝试一些可以解决您代码的问题.

Perhaps if I offered some advice on your current code, you may be able to try some things which could fix your code.

我首先会重写您的check_login.php和redirect.php脚本-事实上,您有两个单独的脚本(可以组合使用)在某个阶段总是会给您带来问题,因为本质上您是在重定向到重定向(当您大声说出来时,这在逻辑上是不合理的).因此,首先将您的脚本重写为一个"auth.php"脚本.并简化需要身份验证的页面的包含,例如:

I would firstly rewrite your check_login.php and redirect.php scripts - the fact that you have two separate scripts (which could be combined) will always give you problems at some stage, because essentially you are redirecting to a redirect (which isn't logically when you say it out a loud). So firstly rewrite your scripts to one 'auth.php' script. And also simplify your include for pages that require authentication, for example:

<?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 ['user_name']和$ _SESSION ['密码"]可能类似于:

Security

You don't need to (and shouldn't!) be storing the actual password in a session, and I would certainly advice against a cookie also. However if you must store the password / username in a cookie, at the very least you must encrypt it using md5() with a salt, etc. So in a nutshell rather than checking $_SESSION['user_name'] and $_SESSION['password'] it could just be something like:

// if the user has no valid session do something:
if ( !isset($_SESSION['id']) ) {


}

关注点分离

我不确定您为何拥有:

Separation of concerns

I'm not sure why your have:

$username = $_POST[username];
$password = $_POST[password];

在您的redirect.php文件中,您是否还在用户登录时使用此脚本?如果您是我(这可能是问题),我认为这不是一个好主意.您应该有一个单独的脚本来处理所有实际的登录功能(包括登录后的重定向).上面的内容仅涉及a)检查用户是否有效/已登录b)重定向用户,否则-实质上是在保护您的网页.

Within your redirect.php file, are you also using this script for when users login? I don't think it's a good idea if you are (which may be the problem). You should have a separate script to handle all actual login functionality (including the redirect after logging in). The above should only be concerned with a) checking if the user is valid / logged in b) redirecting them if not - essentially protecting your web page(s).

您的代码:

//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脚本中尚未设置的内容.

I'm not sure I get this bit in the context, as your basically redirecting them if they have a valid session? Scratch that I don't really understand the whole check_login.php script, as things are a bit backwards (especially when combined with your redirect.php script). You are checking the same variables again ($lr_user) || (!$lr_pass) in your redirect script and making reference to things that have not even been set in your check_login.php script.

可以解决吗? 除非我看过上面的代码块,否则上面的代码块将引用$ _SESSION ['redirect'],否则我认为应该是$ _SESSION ['url']或不要重定向它们.直到redirect.php脚本(如果存在会话可能不会调用),才设置$ _SESSION ['redirect'].

Could be solution? Unless I have over looked something the above code block makes reference to $_SESSION['redirect'], I think that should be either $_SESSION['url'] or just don't redirect them. The $_SESSION['redirect'] doesn't get set until the redirect.php script (which may not get called if the session exists).

很抱歉,如果这不能真正回答您所希望的问题,但是我真的认为这是个很好的机会,可以很好地了解您的脚本并清理/简化它们.理想情况下,您应该使用OOP方法进行查看,即创建会话,重定向,登录类.但是,如果坚持使用普通函数(过程性的),请确保为每个脚本创建一个清晰的分隔符.简而言之:

Sorry if this doesn't really answer your question as you would have liked but I really think this would be a good opportunity to take a good look at your script(s) and clean / simplify them. Ideally you should look at this with an OOP approach, i.e. create a session, redirect, login class. But if sticking with plain functions (procedural) make sure your create a clean separation for each script. So in a nutshell:

  • 不要重复自己,例如为什么$ _SESSION ['redirect']和$ _SESSION ['url']都具有相同的值?
  • 不要重定向到重定向(一个脚本应该处理这个问题)
  • 分开您的顾虑-让登录脚本执行登录过程,并使用身份验证/acl脚本保护您的实际页面(不要将两者结合在一起).

希望以上说明是有道理的,但如果没有,请告诉我.

Hope the above makes sense, but let me know if not.

这篇关于登录重定向时出现无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆