I have a redirect script which does some tracking and then redirects the user to a destination. It looks something like this
class Redirect() {
private function init() {
// analyze parameters
(...)
$this->referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$this->trackVisit($this->referer, $someMoreData);
$destination = $this->getUrlByParameters(...);
$this->redirectUrl = $destination;
}
private function run() {
(...)
header('Location: ' . $this->redirectUrl);
(...)
}
}
$r = new Redirect();
if($r->init()) {
$r->run();
}
What gives me headache is that i can see a referrer on my server and i am saving that in to my db but after redirecting the user it disappears. The destination and all possible subsequent redirects don't have the referrer anymore.
Referrer-Policy is set to 'no-referrer-when-downgrade' but i am always redirect to https so that should not be the issue.
I hope somebody can help me out!
If you redirect the request from a script using header("Location:...") The Å•eferrer will not be preserved. You could possibly pass the referer as a variable in query string:
header('Location: ' . $this->redirectUrl."?ref=".$_SERVER['HTTP_REFERER']);
or with &, if the URL already contains some parameters.
Then you could get the original referer on the other script using $_GET["ref"]
Or you could write headers yourself and append it before the Location header, and then send full headers.
Related
I have an index.php page and I'm using a switch statement to include scripts based on the uri (php request uri) and get the url parameters to do something (activate an account or change a password), then the method returns a message that is printed in the main html page.
The problem is the input url with the get parameters (from the url bar) are still present once the script is executed. And it will be executed again when the user press the login button.
I need to clear (or more exactly redirect, like header) the url from the bar and print the message returned from the method.
If I use header, the $msg will be lost and no message will be printed. If I use another get is the same story again.
// array whitelisting the permitted urls
// just 4: login, send_mail, recover_pwd and register (each pointing to his php file)
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// some more security checks
if ($url != '/send_mail' && $url != '/recover_pwd' && $url != '/register' && $url != '/activateAccount')
$url = '/login'; // this must be always the default page if none of the above are requested.
switch ($url) {
case '/recover_pwd': // here users request a password change
if (isset($_GET['code']) && isset($_GET['email'])) {
include('pages/rp_get.php'); // this is the get script(not included insde the array/html):
//validates the code, changes the password and sends a mail with the new one then we have to redirect the user to the login page and print the message
header('Location: /'); // this will clear the address bar and the $msg var
}
}
break;
case '/activateAccount': // this is just the script that validates the code and activates the account
include('pages/activate_acc.php'); // (not included insde the array/html) then we have to redirect the user to the login page and print the message
header('Location: /');
}
break;
case '/login': // this is the login page
include('pages/header_pages/login_post.php'); // the login post script must be before any DOM output so it can perfom a redirection using header()
break;
default: // i'm not sure if there should be a default case...
$url = $url;
break;
}
// include the main html
include('themes/aet/main.php');
And this is the main.php:
// HTML BASIC STRUCTURE
// BODY -> Header
// MAIN tags
<?php
$include = '/404';
if (array_key_exists($url, $includes)) {
$include = $url; // this includes the pages from the array
}
include($includes[$include]);
?>
// here I print the msg (# is just a temp hack)
if(#$msg != NULL) {
// check what type of message is and print it
}
I need to find a way to do this as clean as optimized. I would not want a heavy index page.
How can I achieve this?
I have a problem with the Mobile Detection Script.
There are two scenarios:
First the script should detect if it's a mobile or not. If mobile, than redirect to another page (this works fine).
The second query should determine, if the person is on the root page or not. If it's not the root page, the layout should be the classic one. (no redirection)
But when I add this line there won't be anymore redirection, even if I open the root page on a mobile.
I also tried to destroy the session on the google_mobile.php (redirected page) and set the $_SESSION['layoutType'] = 'mobile', but anyway the session is set to classic when I open the root page.
Thanks for your help!
Here is the script:
session_start();
require_once 'Mobile_Detect.php';
function layoutTypes() {
return array('classic', 'mobile');
}
function initLayoutType() {
// Safety check.
if (!class_exists('Mobile_Detect'))
return 'classic';
$detect = new Mobile_Detect;
$isMobile = $detect->isMobile();
$layoutTypes = layoutTypes();
// Set the layout type.
if (isset($_GET['layoutType'])) {
$layoutType = $_GET['layoutType'];
} else {
if (empty($_SESSION['layoutType'])) {
$layoutType = ($isMobile ? 'mobile' : 'classic');
} else {
$layoutType = $_SESSION['layoutType'];
}
//check if it's the root page
if ($_SERVER['REQUEST_URI'] != "/")
$layoutType = 'classic';
}
// Fallback. If everything fails choose classic layout.
if (!in_array($layoutType, $layoutTypes))
$layoutType = 'classic';
// Store the layout type for future use.
$_SESSION['layoutType'] = $layoutType;
return $layoutType;
}
$layoutType = initLayoutType();
if ($_SESSION['layoutType'] == 'mobile') {
header("Location: www.example.com/google_mobile.php");
exit;
}
I've tested your code, it seems to work as you described. I'd guess it is a session issue.
session_destroy() does not clear your previous session state in the immediate session. That means your $_SESSION would still be "dirty" in a script even if session_destroy() is the first line in it. It's safer to clear cookies from your browser instead.
One other possible problem would be query string. You're checking the REQUEST_URI and it includes any query string on URI. "/?foo=bar" is certainly not "/". You may want to check SCRIPT_NAME (i.e. $_SERVER['SCRIPT_NAME'] == 'index.php) instead.
In my wordpress project i created a front end log in for users and when user enters a wrong log in information it must redirect the login failed attachment with the url. Below code does it for the first time and then it append to the url continuously when trying to log in. How can i limit this.
add_action('wp_login_failed', 'my_front_end_login_fail');
function my_front_end_login_fail($username){
// Get the reffering page, where did the post submission come from?
$referrer = $_SERVER['HTTP_REFERER'];
// if there's a valid referrer, and it's not the default log-in screen
if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')){
// let's append some information (login=failed) to the URL for the theme to use
wp_redirect($referrer . '&login=failed');
exit;
}
}
Any helps would be appreciated.
try this code
add_action('wp_login_failed', 'my_front_end_login_fail');
function my_front_end_login_fail($username){
// Get the reffering page, where did the post submission come from?
$referrer = $_SERVER['HTTP_REFERER'];
// if there's a valid referrer, and it's not the default log-in screen
if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')){
// let's append some information (login=failed) to the URL for the theme to use
////already not login failed append
if(!strstr($referrer,'&login=failed'))
{
wp_redirect($referrer . '&login=failed');
}
else
{
////if alreday append go to same url
wp_redirect($referrer);
}
exit;
}
}
I am currently using a SESSION variable for redirection. Hoprfully code snippets will make it clear.
addForm.php:
if (!isset($_SESSION['myusername'])){
if (isset($_COOKIE['username'])){
$_SESSION['myusername'] = $_COOKIE['username'];
}
else{
#using a session var to redirect back to addForm.php
$_SESSION['addForm'] = 1;
header("location:loginForm.php");
}
}
LoginSuccess.php
session_start();
if (!isset($_COOKIE['username'])){
header("location:loginForm.php");
}
if (isset($_SESSION['addForm'])){
header("location:addForm.php");
}
the above works (redirects to addForm.php). My question is, are there any risks in doing it this way? is there a better way to do it? I guess i'm looking for 'best practice'.
You have some errors:
The valid header is header('Location: http://www.example.org/script.php'); notice L and full URL?
After each header('Location: http://www.example.org/script.php'); it should be exit();
You cannot rely just on $_COOKIE['username'], you need to have something from password, I mean not the password, maybe an MD5() hashed password in $_COOKIE also. And you should know not to rely on $_COOKIE that much.
In LoginSuccess.php you have to unset($_SESSION['addForm']) before redirection, addForm from session will still be set.
Personnaly, I prefer store the entry current URI in session varible. Then, when my login process are successfull, I use the stored URI to redirect the user to the previous page.
Pseudo Code
if (!isset($_SESSION['userloginobj'])) {
$_SESSION['callbackuri'] = get_current_url_depending_of_your_process();
header('location:' . get_base_url() . 'index.php?do=login');
exit(0);
}
elseif ('login' == get_param('do')) {
// Show the login form
if ( is_login_successfull() ) {
$_SESSION['userloginobj'] = "userinfo";
header('location:' . $_SESSION['callbackurl']);
exit(0);
}
}
else {
// Normal process
}
But your proccess seems to be a good start if you don't use a framework.
In messaging system of my project when you get a message from a user you a email alert saying that the another user has sent a message to view the message click here (i.e the url of message) So if the user is not logged in to system he gets redirect to login page and after login it should get back to the referer url. I have made a basecontoller in core folder and extending the CI_controller the authenticating code is as follows.
function authenticate($type = 'user')
{
if($type == 'user')
{
if($this->user_id)
{
// user is logged in. check for permissions now
}
else
{
// user isnt logged in. store the referrer URL in a var.
if(isset($_SERVER['HTTP_REFERER']))
{
$redirect_to = str_replace(base_url(),'',$_SERVER['HTTP_REFERER']);
}
else
{
$redirect_to = $this->uri->uri_string();
}
redirect('user/login?redirect='.$redirect_to);
exit;
}
}
if($type == 'admin')
{
if($this->session->userdata('admin_id') && $this->session->userdata('user_type') ==5)
{
// Admin is logged in
}
else
{
redirect('admin/login');
exit;
}
}
}
The referer url is "http://example.com/project/pm/view_conversation?id=11"
now the problem is I am getting referer url till view_conversation and not able to get the id part.
Any suggestion ?
Thank you.
This can help:
CI 2+
https://www.codeigniter.com/userguide2/libraries/user_agent.html
CI 3+
http://www.codeigniter.com/userguide3/libraries/user_agent.html
Below solution is for Codeigniter version 3
$this->load->library('user_agent');
if ($this->agent->is_referral())
{
echo $this->agent->referrer();
}
UPDATE: interesting and useful information on how to obtain referrer information with the same user_agent library
https://www.tutorialandexample.com/user-agent-class/
How about just
redirect($_SERVER['HTTP_REFERER']);
Using php's $_SERVER global variable.
This worked for me!
Put that code in your Login Controler
function index() {
$this->load->library('user_agent'); // load user agent library
//Set session for the referrer url
$this->session->set_userdata('referrer_url', $this->agent->referrer() );
}
After Login Redirection Code
// user is authenticated if referrer is there
if( $this->session->userdata('referrer_url') ) {
//Store in a variable so that can unset the session
$redirect_back = $this->session->userdata('referrer_url');
$this->session->unset_userdata('referrer_url');
redirect( $redirect_back );
}
Because you have double question mark in the url, the browser ignores the url part after the second one. Use urlencode for you redirect part, like so:
redirect('user/login?redirect='.urlencode($redirect_to));
I've tested it out and it works this way.
By default CI is configured to ignore the query part of the URL (the part after the '?').
See: http://codeigniter.com/user_guide/general/urls.html