Phiên PHP bị mất sau khi chuyển hướng


132

Làm cách nào để giải quyết vấn đề mất phiên sau khi chuyển hướng trong PHP?

Gần đây, tôi gặp phải một vấn đề rất phổ biến là mất phiên sau khi chuyển hướng. Và sau khi tìm kiếm thông qua trang web này, tôi vẫn không thể tìm thấy giải pháp nào (mặc dù điều này là gần nhất).

Cập nhật

Tôi đã tìm thấy câu trả lời và tôi nghĩ rằng tôi sẽ đăng nó ở đây để giúp bất cứ ai gặp vấn đề tương tự.


1
Câu hỏi là làm thế nào để giải quyết vấn đề mất phiên sau khi chuyển hướng trong PHP. Tôi đã tìm ra câu trả lời rồi, chỉ cần đăng nó lên đây để cho người khác biết. Bởi vì giải pháp của tôi không có trên StackOverflow.
dayuloli

2
Điều đó tốt, nhưng đây là một trang web QA. Hãy làm cho câu hỏi của bạn một câu hỏi.
jeremy

Tôi đã không nhận thấy nó là từ bạn. Tuy nhiên, trang web này là dành cho câu hỏi, không phải cho câu trả lời cho câu hỏi bạn đã biết.
Aris


21
@Aris Điều đó không đúng, khi mọi người có câu hỏi về mã hóa, họ tìm đến StackOverflow để được giúp đỡ. Nếu không có câu trả lời, thì họ không thể nhận được sự giúp đỡ cần thiết. Tôi đang cố gắng cung cấp câu trả lời đó.
dayuloli

Câu trả lời:


208

Đầu tiên, thực hiện các kiểm tra thông thường sau:

  1. Hãy chắc chắn session_start();được gọi trước khi bất kỳ phiên nào được gọi. Vì vậy, đặt cược an toàn sẽ là đặt nó ở đầu trang của bạn, ngay sau <?phptuyên bố mở trước bất cứ điều gì khác. Cũng đảm bảo không có khoảng trắng / tab trước khi khai <?phpbáo mở .
  2. Sau khi headerchuyển hướng, hãy kết thúc tập lệnh hiện tại bằng cách sử dụng exit();(Những người khác cũng đã đề xuất session_write_close();session_regenerate_id(true), bạn cũng có thể thử những tập lệnh đó, nhưng tôi sẽ sử dụng exit();)
  3. Đảm bảo cookie được bật trong trình duyệt bạn đang sử dụng để kiểm tra.
  4. Đảm bảo register_globalslà tắt, bạn có thể kiểm tra điều này trên php.initập tin và cũng có thể sử dụng phpinfo(). Tham khảo điều này như làm thế nào để tắt nó.
  5. Hãy chắc chắn rằng bạn đã không xóa hoặc làm trống phiên
  6. Đảm bảo rằng khóa trong $_SESSIONmảng siêu lớp của bạn không bị ghi đè ở bất cứ đâu
  7. Hãy chắc chắn rằng bạn chuyển hướng đến cùng một tên miền. Vì vậy, chuyển hướng từ một www.yourdomain.comđể yourdomain.comkhông mang phiên về phía trước.
  8. Hãy chắc chắn rằng phần mở rộng tập tin của bạn là .php(nó xảy ra!)

Bây giờ, đây là những lỗi phổ biến nhất, nhưng nếu họ không thực hiện được mánh khóe thì vấn đề rất có thể xảy ra với công ty lưu trữ của bạn. Nếu mọi thứ hoạt động trên localhostnhưng không phải trên máy chủ từ xa / thử nghiệm của bạn, thì đây rất có thể là thủ phạm. Vì vậy, hãy kiểm tra cơ sở kiến ​​thức của nhà cung cấp dịch vụ lưu trữ của bạn (cũng thử diễn đàn của họ, v.v.). Đối với các công ty như FatCow và iPage, họ yêu cầu bạn chỉ định session_save_path. Vì vậy, như thế này:

session_save_path('"your home directory path"/cgi-bin/tmp');
session_start();

(thay thế "đường dẫn thư mục chính của bạn" bằng đường dẫn thư mục chính thực tế của bạn. Điều này thường nằm trong bảng điều khiển của bạn (hoặc tương đương), nhưng bạn cũng có thể tạo một test.phptệp trên thư mục gốc và gõ:

<?php echo $_SERVER['SCRIPT_FILENAME']; ?>

Bit trước 'test.php' là đường dẫn thư mục chính của bạn. Và tất nhiên, hãy chắc chắn rằng thư mục thực sự tồn tại trong thư mục gốc của bạn. (Một số chương trình không tải lên các thư mục trống khi đồng bộ hóa)


8
+1 được viết rất tốt, nếu tất cả đều thất bại, chỉ cần sử dụng cookie (tạo ngẫu nhiên một chuỗi và lưu trữ nó trong db và sử dụng nó làm giá trị cookie của bạn).
Dave Chen

2
chuyển đổi giữa http vàn https cũng có thể là một vấn đề stackoverflow.com/questions/441496/
Khăn

4
Lưu ý rằng kể từ php 5.4.0 register_globals đã bị xóa, vì vậy nó sẽ không còn gây ra sự cố nữa
anthonygore

2
Kiểm tra nhật ký lỗi máy chủ web; trong trường hợp của tôi, đã xảy ra lỗi "Không thể ghi dữ liệu phiên (tệp). Vui lòng xác minh rằng cài đặt hiện tại của session.save_path là chính xác". Các quyền đã sai trên thư mục save_path.
timbonicus

Bất kỳ lý do tại sao các phiên của tôi sẽ được lưu trữ ở một nơi khác ngoài session.save_path?
Justin

26

bạn nên sử dụng "exit" sau cuộc gọi tiêu đề

header('Location: http://www.example.com/?blabla=blubb');
exit;

Có một lỗi đối với Gecko (ví dụ Waterfox, Firefox, SeaMonkey) trong đó nếu có bất kỳ đầu ra dữ liệu nào (ví dụ echo ' ';) hoặc khoảng trắng của bất kỳ loại nào, nó sẽ hoàn toàn bỏ qua tiêu đề vị trí.
Giăng

18

Tôi đã thử tất cả các giải pháp có thể, nhưng không có giải pháp nào phù hợp với tôi! Tất nhiên, tôi đang sử dụng một dịch vụ lưu trữ chia sẻ.

Cuối cùng, tôi đã khắc phục được vấn đề bằng cách sử dụng 'url tương đối' bên trong tiêu đề chuyển hướng!

header("location: http://example.com/index.php")

vô hiệu hóa cookie phiên

header("location: index.php")

làm việc như người ở !


7

Tôi đã từng gặp vấn đề tương tự. Tôi đã làm việc với nó trong vài giờ và nó làm tôi phát điên.

Trong trường hợp của tôi, sự cố là 404 được gọi do thiếu favicon.ico chỉ trong Chrome và Firefox. Các nhà hàng hải khác làm việc tốt.


Chỉ muốn cảm ơn bạn về câu trả lời này, khiến tôi nhận ra rằng các yêu cầu 404 cho hình ảnh đã được Varnish chuyển tiếp tới PHP mà không có bất kỳ cookie nào và do đó các phiên mới được tạo ra liên tục. Có thể không bao giờ có thể tìm ra nó mà không có bạn.
Pascal Zajac

Tôi có cùng một vấn đề, favicon.ico của tôi đã được chuyển hướng (302 chuyển hướng từ tên miền phụ sang tên miền chính) và do đó, tạo ra một phiên mới mỗi lần. Cảm ơn rất nhiều!
simdrouin

4

Khi tôi sử dụng đường dẫn tương đối "dir / file.php" với hàm header () trong công việc cho tôi. Tôi nghĩ rằng phiên này không được lưu vì một số lý do khi bạn chuyển hướng bằng cách sử dụng url đầy đủ ...

//Does retain the session info for some reason
header("Location: dir");

//Does not retain the session for some reason
header("Location: https://mywebz.com/dir")

3

Điều này làm tôi bối rối trong một thời gian dài (và bài đăng này rất tuyệt để tìm!) Nhưng đối với bất kỳ ai khác vẫn không thể có phiên giữa các trang chuyển hướng để làm việc ... Tôi đã phải truy cập vào tệp php.ini và bật cookie :

session.use_cookies = 1 

Tôi nghĩ rằng các phiên làm việc mà không có cookie ... thực tế tôi biết họ NÊN ... nhưng điều này đã khắc phục vấn đề của tôi ít nhất cho đến khi tôi có thể hiểu những gì có thể xảy ra trong bức tranh lớn hơn.


Tôi không biết phiên có thể hoạt động mà không cần cookie! Học điều mới mỗi ngày! lập trình
viênviewview.com/index.php/php

tất nhiên họ CÓ THỂ làm việc mà không cần cookie phụ thuộc vào cấu hình của bạn. Nhưng bạn nên biết những gì bạn làm. Và có một lý do tốt để làm như vậy. Bởi vì nó kém an toàn. và trong trường hợp bạn phải làm việc vì lý do gì mà không có cookie. Ít nhất bạn nên định cấu hình ini_set ('session.use_strict_mode', '1'); và thường có thời gian phiên ngắn và sau khi người dùng đăng nhập sử dụng session_regenerate_id (). Nhưng được cảnh báo nếu một số người dùng đăng một liên kết đến một trang web trên máy chủ của bạn trong một diễn đàn, những người thực sự nhấp vào liên kết này sẽ đảm nhận phiên này. Có lẽ kiểm tra ip cũng là một ý tưởng tốt.
Michael

3

Tôi đã có một vấn đề tương tự, mặc dù bối cảnh của tôi hơi khác nhau. Tôi đã có một thiết lập phát triển cục bộ trên một máy có tên máy chủ windowsvà địa chỉ IP 192.168.56.2.

Tôi có thể truy cập hệ thống bằng một trong hai cách sau:

Sau khi đăng nhập, mã PHP của tôi sẽ chuyển hướng bằng cách sử dụng:

header('http://windows/');

Nếu tên miền trước đó được sử dụng để truy cập hệ thống thì không windows, dữ liệu phiên sẽ bị mất. Tôi đã giải quyết điều này bằng cách thay đổi mã thành:

header('http://'.$_SERVER['HTTP_HOST'].'/');

Bây giờ nó hoạt động bất kể tên miền địa phương hoặc địa chỉ IP mà người dùng đặt vào.

Tôi hy vọng điều này có thể hữu ích cho một ai đó.


3

Tôi gặp vấn đề này trên một trang cụ thể. Tôi đã đặt giá trị $ _SESSION trong các trang khác ngay trước khi chuyển hướng và mọi thứ đều hoạt động tốt. Nhưng trang đặc biệt này không hoạt động.

Cuối cùng tôi nhận ra rằng trong trang cụ thể này, tôi đã phá hủy phiên ở đầu trang nhưng không bao giờ bắt đầu lại. Vì vậy, chức năng hủy của tôi thay đổi từ:

function sessionKill(){

    session_destroy();

}

đến:

function sessionKill(){

    session_destroy();
    session_start();

}

Và mọi thứ đã làm việc!


3

Tôi đã có cùng một vấn đề. Tất cả một số biến đột ngột của phiên của tôi sẽ không tồn tại sang trang tiếp theo. Vấn đề hóa ra là (trong php7.1) vị trí tiêu đề của bạn không được có WWW trong đó, ví dụ https: // mysite . là ok, https: //www.mysite . sẽ mất các trang phiên biến. Không phải tất cả, chỉ trang đó.


Đó là bởi vì www.mysite.comđược xem như là một miền hoàn toàn khác so với blog.mysite.comhoặc đơn giảnmysite.com
dayuloli

2

Tôi đã vật lộn với điều này trong nhiều ngày, kiểm tra / thử tất cả các giải pháp, nhưng vấn đề của tôi là tôi đã không gọi session_start();lại sau khi chuyển hướng. Tôi chỉ cho rằng phiên là "vẫn còn sống".

Vì vậy, đừng quên điều đó!


Đúng! đây cũng là vấn đề của tôi Tôi nghĩ rằng bắt đầu một phiên PHP giống như bật đèn cho cả nhà. Tôi không nhận ra bạn phải bật công tắc cho từng phòng mà bạn bước vào.
Dale Thompson

1

Tôi đã có cùng một vấn đề và tìm thấy cách dễ nhất. Tôi chỉ cần chuyển hướng đến .html chuyển hướng với 1 dòng JS

<!DOCTYPE html>
<html>
<script type="text/javascript">
<!--
window.location = "admin_index.php";
//–>
</script>
</html>

thay vì PHP

header_remove();
header('Location: admin_login.php');
die;

Tôi hi vọng cái này giúp được.

Yêu Gram


1

Nếu bạn đang sử dụng session_set_cookie_params()bạn có thể muốn kiểm tra xem bạn đang đi qua các param thứ tư $securenhư true. Nếu là bạn, thì bạn cần truy cập url bằng https.

Thông số $securelà đúng có nghĩa là Phiên chỉ có sẵn trong một yêu cầu an toàn. Điều này có thể ảnh hưởng đến bạn tại địa phương nhiều hơn trong giai đoạn hoặc môi trường sản xuất.

Đề cập đến nó bởi vì tôi đã dành hầu hết ngày hôm nay để cố gắng tìm ra vấn đề này, và đây là điều đã giải quyết nó cho tôi. Tôi mới được thêm vào dự án này và không ai đề cập rằng nó yêu cầu https.

Vì vậy, bạn có thể sử dụng https cục bộ hoặc bạn có thể đặt $secureparam thành FALSEvà sau đó sử dụng http cục bộ. Chỉ cần chắc chắn để đặt nó trở lại đúng khi bạn đẩy các thay đổi của bạn lên.

Tùy thuộc vào máy chủ cục bộ của bạn, bạn có thể phải chỉnh sửa DocumentRoottrong httpd-ssl.confmáy chủ để url cục bộ của bạn được cung cấp https.


1

Một lý do có thể khác:

Đó là không gian lưu trữ máy chủ của tôi. Không gian đĩa máy chủ của tôi trở nên đầy đủ. Vì vậy, tôi đã xóa một vài tệp và thư mục trong máy chủ của mình và thử.

Nó đã được làm việc !!!

Tôi đang lưu phiên của mình trong AWS Dynamo DB, nhưng nó vẫn mong đợi một số không gian trong máy chủ của tôi để xử lý phiên. Không chắc chắn lý do tại sao!!!


1

Nếu bạn đang sử dụng Laravel và bạn gặp phải sự cố này, điều bạn cần là lưu dữ liệu phiên của mình trước khi chuyển hướng.

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;

0

Tôi cũng gặp vấn đề tương tự với việc chuyển hướng không hoạt động và đã thử tất cả các giải pháp tôi có thể tìm thấy, chuyển hướng tiêu đề của tôi đang được sử dụng trong một biểu mẫu.

Tôi đã giải quyết nó bằng cách đặt chuyển hướng tiêu đề vào một trang php khác 'signin_action.php' và chuyển các tham số biến qua tôi muốn trong các tham số url và sau đó gán lại chúng ở dạng 'signin_action.php'.

đăng nhập

if($stmt->num_rows>0) {
$_SESSION['username'] = $_POST['username'];
echo '<script>window.location.href = "http://'.$root.'/includes/functions/signin_action.php?username='.$_SESSION['username'].'";</script>';
error_reporting(E_ALL);

đăng nhập

<?php
require('../../config/init.php');
$_SESSION['username'] = $_GET['username'];
if ($_SESSION['username']) {

echo '<script>window.location.href = "http://'.$root.'/user/index.php";</script>';
exit();
} else {
echo 'Session not set';
}

?>

Nó không phải là một công việc đẹp xung quanh nhưng nó đã làm việc.


0

Đối với tôi, lỗi là tôi đã cố lưu một đối tượng không thể xác định được trong phiên để một ngoại lệ được đưa ra trong khi cố gắng viết phiên. Nhưng vì tất cả các mã xử lý lỗi của tôi đã ngừng bất kỳ hoạt động nào, tôi không bao giờ thấy lỗi.

Tôi có thể tìm thấy nó trong nhật ký lỗi Apache.


0

Chỉ để ghi lại ... Tôi gặp vấn đề này và sau vài giờ thử mọi thứ, vấn đề là đĩa đã đầy, và các phiên php không thể được ghi vào thư mục tmp ... vì vậy nếu bạn gặp vấn đề này, hãy kiểm tra xem quá...


Câu trả lời này đã làm việc cho tôi. Chúng tôi chạy một hình ảnh máy Amazon với nginx. Dường như có một lỗi mà thư mục phiên không thuộc quyền sở hữu của người dùng chính xác (trong trường hợp của chúng tôi www) vì vậy việc thực hiện chown -R www.wwwtrên thư mục phiên khắc phục sự cố.
Joshua

0

Đối với tôi, Firefox đã lưu trữ id phiên (PHPSESSID) trong cookie, nhưng Google Chrome đã sử dụng tham số GET hoặc POST. Vì vậy, bạn chỉ phải đảm bảo rằng tập lệnh trả về (đối với tôi: thanh toán paypal) cam kết PHPSESSID trong url hoặc tham số POST.


0

Sau khi thử nhiều giải pháp ở đây trên SO và các blog khác ... điều làm việc cho tôi là thêm .htaccess vào trang web gốc của tôi.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]

0

Nếu bạn đang sử dụng Wordpress, tôi phải thêm hook này và bắt đầu phiên trên init:

function register_my_session() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'register_my_session');

0

Không có gì làm việc cho tôi nhưng tôi đã tìm thấy nguyên nhân gây ra sự cố (và đã giải quyết nó):

Kiểm tra cookie trình duyệt của bạn và đảm bảo rằng không có cookie phiên php trên các tên miền phụ khác nhau (như một cho " www.website.com " và một cho " website.com ").

Điều này được gây ra bởi một javascript sử dụng tên miền phụ không chính xác để đặt cookie và để mở các trang trong iframe.


0

Trước hết, hãy chắc chắn rằng bạn đang gọi session_start()trước khi sử dụng $_SESSIONbiến.

Nếu bạn đã tắt báo cáo lỗi, hãy thử bật và xem kết quả.

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

Những lý do phổ biến nhất không được đề cập trong câu trả lời của @ dayuloli:

  1. Vấn đề không gian đĩa. Đảm bảo dung lượng đĩa của bạn không đầy, bạn cần một số dung lượng để lưu trữ tệp phiên.

  2. Thư mục phiên có thể không được ghi. Bạn có thể kiểm tra nó vớiis_writable(session_save_path())


0

Tôi đã có cùng một vấn đề và tôi đã tìm kiếm trong mã của mình để tìm câu trả lời. Cuối cùng tôi đã tìm thấy lưu trữ của tôi gần đây đã cập nhật phiên bản PHP trên máy chủ của tôi và không thiết lập chính xác session_save_paththam số trên php.initệp.

Vì vậy, nếu ai đó đọc được điều này, vui lòng kiểm tra php.inicấu hình trước bất cứ điều gì khác.


0

Đảm bảo session_write_closekhông được gọi giữa session_start()và khi bạn đặt phiên.

session_start();

[...]

session_write_close();

[...]

$_SESSION['name']='Bob'; //<-- won't save

0

Bây giờ GDPR là một điều, những người truy cập câu hỏi này có thể sử dụng tập lệnh cookie. Vâng, kịch bản đó gây ra vấn đề cho tôi. Rõ ràng, PHP sử dụng một cookie được gọi PHPSESSIDđể theo dõi phiên. Nếu tập lệnh đó xóa nó, bạn sẽ mất dữ liệu của mình.

Tôi đã sử dụng tập lệnh cookie này . Nó có một tùy chọn để kích hoạt cookie "thiết yếu". Tôi đã thêm vào PHPSESSIDdanh sách, tập lệnh dừng xóa cookie và mọi thứ bắt đầu hoạt động trở lại.

Bạn có thể có thể kích hoạt một số cài đặt PHP để tránh sử dụng PHPSESSID, nhưng nếu tập lệnh cookie của bạn là nguyên nhân gây ra sự cố, tại sao không khắc phục điều đó .


0

Tôi đã khắc phục sự cố này sau nhiều ngày gỡ lỗi và tất cả là do URL trả lại của tôi đến từ PayPal Express Checkout không có 'www'. Chrome nhận ra rằng các tên miền nên được đối xử như nhau nhưng đôi khi các trình duyệt khác thì không. Khi sử dụng phiên / cookie và đường dẫn tuyệt đối, đừng quên 'www'!


0

Tôi đã sửa bằng cách cấp quyền ghi nhóm cho đường dẫn nơi lưu trữ tệp phiên của PHP. Bạn có thể tìm đường dẫn phiên với hàm session_save_path ().


0

Hôm nay tôi gặp vấn đề này trong một dự án và tôi đã phải thay đổi tham số này thành false (hoặc xóa các dòng, theo mặc định là bị tắt):

ini_set( 'session.cookie_secure', 1 );

Điều này xảy ra vì dự án thực tế chỉ hoạt động trên http chứ không phải https. Tìm thêm thông tin trong các tài liệu http://php.net/manual/en/session.security.ini.php


0
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
session_start();

Quá muộn để trả lời nhưng điều này làm việc cho tôi


0

Đối với tôi đây là lỗi cấp phép và điều này đã giải quyết nó:

chown -R nginx: nginx / var / opt / remi / php73 / lib / php / session

Tôi đã thử nghiệm một vài giờ trên PHP và thử nghiệm cuối cùng tôi đã làm là tôi đã tạo hai tệp session1.php và session2.php.

phiên1.php:

session_start();

$_SESSION["user"] = 123;

header("Location: session2.php");

phiên2.php:

session_start();

print_r($_SESSION);

và nó đã in một mảng trống.

Tại thời điểm này, tôi nghĩ rằng nó có thể là một vấn đề máy chủ và trên thực tế, nó đã được.

Hy vọng điều này sẽ giúp được ai đó.


1
Chown là một giải pháp BAD, vì nó sẽ được thay đổi trở lại giá trị mặc định khi cập nhật gói. Xem bình luận trong cấu hình nhóm mặc định (www.conf). Cách thích hợp nếu sử dụng thư mục khác ngoài thư mục apache (ví dụ: / var / lib / php / nginx / session)
Remi Collet

Bạn đúng rồi. Cập nhật gói là lý do cho vấn đề của tôi ở nơi đầu tiên. Nhưng vì đó là cách nó đã được thực hiện và tôi cần một số giải pháp nhanh chóng, điều này có ích. Quản trị viên SYS của tôi đã giải quyết nó, tôi không tốt với Linux.
temo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.