0

我有许多前端功能,这些功能是根据用户是否登录(即显示的菜单项)触发的,但是当用户登录时我无法触发它们,除非它们被重定向或页面被刷新。

$logged_in用户登录后如何更改要设置的值?这些功能都可以正常工作,包括$_SESSION['SESS_USER_ID'] = $member['user_id'];登录后的设置。

Index.php (大部分代码也在整个站点中使用)

在文件的开头:

<?php    
require_once('auth.php'); // This file starts session, and checks if(!isset($_SESSION['SESS_USER_ID']) || (trim($_SESSION['SESS_USER_ID']) == ''))  
require_once('config.php'); // Connects to database connection   
$user_id = $_SESSION['SESS_USER_ID'];       
$logged_in = (isset($_SESSION['SESS_USER_ID']));
?>

然后由 $logged_in 触发相关函数,并遵循以下基本格式:

<?php if ($logged_in) : ?>
// Some HTML or Script
<?php else : ?>
// Some HTML or Script
<?php endif; ?>

登录形式和功能

如果某些 AJAX 无关紧要,我深表歉意 - 我真的不了解 AJAX 并重新利用现有代码。

<form id="loginForm" name="loginForm" action="login-exec_pdo.php"  method="post">  
<label for="user_name">Username </label><input type="text" name="user_name" required />
<label for="password">Password </label><input type="text" name="password" required />
<div id="return_result"></div><div id="messageBox5">Please complete the highlighted    fields</div>                  
<input type="submit" id="login" value="Sign in" />
</form>

<script type="text/javascript">
$(function () { $('#loginForm').validate({          
rules: {user_name: {required: true, minlength: 2,}, password: {required: true, minlength: 6,},}, messages: {user_name: "", password: "",},      
errorLabelContainer: "#messageBox5", 
submitHandler: function (form){
  $.ajax({
    type: 'POST',
    url: 'login-exec_pdo.php',
    data: $("#loginForm").serialize(),
    success: function(data) {   
      if(data == "true") {
        $("#loginForm").fadeOut("fast");
      }
      else {
        writeToTarget('return_result', 'Incorrect Username or Password');
}  }  });  }   });  });  
</script>

login-exec.php 文件

<?php
session_start();
require_once('config/config_pdo.php'); // Includes db connection, salt, & PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
$password = $_POST['password'];  
$hashedPassword = sha1($salt . $password); 

try {  
   $stmt_user = $conn->prepare("SELECT * FROM customer_info WHERE user_name = :user_name and password = :hashedPassword");  
   $stmt_user->bindValue(':user_name', $_POST['user_name'], PDO::PARAM_STR); 
   $stmt_user->bindValue(':hashedPassword', $hashedPassword);     
   $stmt_user->execute();                 
   session_regenerate_id();                  
   $member = $stmt_user->fetch();                 
   if($member) {                  
      $_SESSION['SESS_USER_ID'] = $member['user_id'];  
      $_SESSION['SESS_USER_NAME'] = $member['user_name'];             
      session_write_close(); 
      echo "true";                 
      exit();
   }else {
      echo "false";
      exit();
   }                    
}catch(PDOException $e) {
  echo $e->getMessage();
}                 
?>

我还尝试使用 javascript 和 php 在登录功能(如上所示)中的成功功能中设置它,但它要么没有设置它和/或阻止登录功能正确完成。我尝试过的一些事情是: if ($logged_in) : $logged_in = (isset($_SESSION['SESS_USER_ID'])); $logged_in = "true";$logged_in = 1;

4

2 回答 2

1

如果您通过 AJAX 提交登录请求,则主页的 PHP 不会受到影响,因为它是服务器端的并且已经编写好了。如果您无法通过 AJAX 拨打电话,您可以:

1) 使用 success() 函数刷新对话框/框架/使用 $logged_in 变量的页面

2) 使用 success() 函数进行另一个 AJAX 调用以检索页面

3)加载所有内容(取决于它的敏感程度),但将“登录”材料设置为display:none;,并使用 success() 执行类似的操作$('.logged-in-user-stuff').show();

于 2013-01-02T03:27:30.107 回答
1

介绍

有点伤脑筋,所以让我先展示你明显的错误

错误 #1
您不能直接使用 JavaScript 设置 PHP 变量。这只能通过与 JSON/XML 交换来完成

submitHandler: function (form){

    $.ajax({type: 'POST', url: 'login-exec_pdo.php', data: $("#loginForm").serialize() ...

    success: function(data) {

        if (data == "true") { 

            $("#loginForm").fadeOut("fast");

            // THIS IS WHERE I'VE TRIED TO SET $logged_in


            // 1. You can't set $logged_in to true right from this point
            // You should send JSON or XML back to PHP invoking a new nested ajax call
            // and then parse that stuff in PHP and then send the parsed stuff back to JavaScript.
            // However, this is some kind of bad approach, because A) you invoke a nested ajax call
            // B) you make it even worse to debug and maintain C) 

            // 2. You serialized the form but never used it

        ....

错误 #2

混合职责和代码重复。究竟是什么:将数据库处理程序(包括数据库配置)与用户责任混合(参见下面的描述)

$stmt_user = $conn->prepare("SELECT * FROM customer_info WHERE user_name = :user_name and password = :hashedPassword");  <-- LIMIT 1 keyword should be appended
$stmt_user->bindValue(':user_name', $_POST['user_name'], PDO::PARAM_STR); 
$stmt_user->bindValue(':hashedPassword', $hashedPassword); //<-- btw, you've missed PDO::PARAM_STR here
$stmt_user->execute();
...                
session_regenerate_id();  //<-- This should be done after successful authorization, not before                  
$member = $stmt_user->fetch();                 
if($member) {    //if you have error_reporting(E_ALL) you'll see a E_NOTICE 
   $_SESSION['SESS_USER_ID'] = $member['user_id'];
   session_write_close(); 
   echo "true"; //<-- Single quotes should be used instead of double ones.
   exit();
}else {
   echo "false";
   exit();
}  

那么好吧。假设这是一个登录页面。但是在真实的场景中,用户的个人资料页面也将使用数据库。根据您的代码,您将不得不实现相同的数据库处理程序两次甚至更多......(见下面的评论)

错误 #3
根本没有错误跟踪 & 依赖于客户端验证。

基本上,您永远不应该相信客户端验证,因为任何人都可以简单地在浏览器中禁用 JavaScript。然后他可以轻松地将“无效”数据发送到 PHP 脚本。始终进行服务器端验证!但这并不意味着您根本不应该使用客户端验证。
相反,当它们来自未启用/支持 JS 的浏览器时,您应该处理这种情况。您可以自己尝试,只需在浏览器中禁用 JavaScript,然后进入您的网站...

错误 #4
更不用说代码重复了,代码本身的结构并不好。这是不应该的。在这里,我说的是 JavaScript 和 PHP 代码......


现在,你应该如何解决这个问题

我不确定您是否会遵循上述建议(以防您没有时间或意愿),所以让我先回答您的原始问题。

$logged_in用户登录后如何更改要设置的值?

简而言之:这是一个 PHP 变量!因此应该在 PHP 中设置它对我来说很像,即使你$logged_in在用户登录后设置为 TRUE,你也错过了某个地方session_start()。但是,根本不要使用这个变量!而是定义一个函数,例如,is_user_logged()因为如果出现问题,它更可靠且“可捕获”。好的,接下来,

为了让生活更轻松,只需定义这些函数:

/**
 * Checks whether user logged in
 * 
 * @return boolean TRUE if user is logged in
 *                 FALSE if not
 */
function is_user_logged(){
   //if session isn't started yet
   if ( session_id() == ''){
      // do start it now
      session_start();
   }

   if ( isset($_SESSION['SESS_USER_ID']) ){
      return true; 
   }

   return false;
}

/**
 * Retrieves an ID of the logged user if he's really logged
 * NULL otherwise
 * 
 * @return string|null
 */
function get_logged_user_id(){

   if ( is_user_logged() === TRUE ){
      return $_SESSION['SESS_USER_ID'];
   }

   return null;
}


/**
 * "Marks" given user id as a logged one
 * 
 * @return void
 */
function register_user_id_as_logged($id){

   //will start session also if not started yet
   if ( is_user_logged() !== TRUE ){
      $_SESSION['SESS_USER_ID'] = $id;
   }
}

将这些函数放在文档的顶部。

现在改变:

在 HTML 模板中排名第一

<?php if ( TRUE === is_user_logged() ) : ?>

// Some HTML or Script if logged

<?php else : ?>

// Some HTML or Script if not logged

<?php endif; ?>

#2

...
$member = $stmt_user->fetch();                 
if($member) {                  
   $_SESSION['SESS_USER_ID'] = $member['user_id'];                 
   session_write_close(); 
   echo "true";
   exit;

到:

$member = $stmt_user->fetch();                 
if ($member) {  //<-- Somehow my heart tells me it should be - if ( isset($member[0]) )

   register_user_id_as_logged($member['user_id']); //<-- and this should be $member[0]['member_id']
   session_regenerate_id();
   exit('true');



if (data == "true") { 


$("#loginForm").fadeOut("fast"); // <-- not required if you're going to do redirect


// THIS IS WHERE I'VE TRIED TO SET $logged_in  <-- if you already in this "block", a "session id" is already set and it "works"
// all you need to do is just to redirect,like:

window.location = 'some_profile_page.php';

现在我自己的建议

提示 #1

确保 JavaScript 未被禁用。你可以简单地这样做,比如,

<!DOCTYPE html>
<html>
<head>

...

<!--So, when JS is disabled, it would redirect to /error.php page automatically -->
<noscript>

    <meta http-equiv="REFRESH" content="0; url=/error.php" />

</noscript> 

 ...
</head>


...
</html>


在所有 HTML 文档中使用这个技巧。

提示 #2

您应该将所有与配置文件相关的逻辑封装到一个类中。它应该类似于这个:

class Profile {

    private $db;

    public function __construct(PDOAdapter $db)
    {
        $this->db = $db;
    }


    public function login($username, $password)
    {
        //do query here and return boolean
    }

    public function logout()
    {
        //destroy session here
    }


    public function isLogged()
    {
        // check if session key exists and its a valid one here
    }

    private function registerAsLogged()
    {
        //....
    }
}
于 2013-01-02T18:35:20.093 回答