i have a jquery Ajax request happening on a page. On php side i am checking if the session is active and doing something. If the session is not active i want to redirect the user to another page in php(header redirect). how do i do it.
I know how to achieve it in javascript(i.e if session_fail then change window.location but is there something that i can do in php/cakephp
Redirects only say "The data you requested can be found here".
HTTP provides no way to say "Even though you requested a resource to go inside a page, you should should leave that page and go somewhere else".
You need to return a response that your JavaScript understands to mean "Go to a different location" and process it in your own code.
If I understand what you want to happen then this is how I'm implementing it. It's in Prototype instead of jQuery but it shouldn't take you long to translate:
new Ajax.Request('process.php', {
on401: function(response) {
var redirect = response.getHeader('Location');
document.location = redirect;
}
});
In your PHP, output the following if the session is inactive:
header('Location: http://example.com/login.php', true, 401);
exit;
This is what you would want in your php IF THIS WERE A REGULAR REQUEST, NOT AN AJAX
if (isset($_SESSION)) doSomething();
else header("Location: otherUrl");
Since this is an Ajax call, you are not passing control to the php, but just trying to get a response that (likely) fills a particular section of your page. You do not mention what jQuery ajax function you use, but it matters. I would imagine you are using either $.get() or $(element).load() ??
Without knowing the particulars, this is my best suggestion for you.
Ajax call: $.get(url, callbackFunc);
php:
if(isset($_SESSION)) echoSomething() else echo("redirect");
callbackFunc:
function(data)
{ if (data == "redirect") window.location = otherUrl;
else
$("#desiredElement").html(data);
}
Related
I made an ajax call to the php script, which would indicate whether the information input by the user were valid and he would be authorized to sign in.
The thing is I'm not really sure about the session variable. Can that php script save session id variable and pass it onto the next php page, where jquery would redirect me upon successful ajax call?
Or would php itself redirect me using header location?
I hope I made myself clear. It is a theoretical question.
You would set the userid in the session and return a "success" condition back to ajax. the ajax success callback would inspect the returned data to determine if the login was successful and act accordingly (for example, redirect to a logged-in homepage)
You cant not redirect with PHP in this case because the headers are not returned in the http response.
you can set a variable in the response that returns the state of your php proccess.
something like
data = array(
"connect"=>true
);
or
data = array(
"connect"=>false,
"errors"=>"There is an error in your request"
);
then in the success: function you can check if the variable is true or false and redirect if you need to.
success: function(response){
if(response.connect){
//succeded
}else{
//not succeded
}
hope that helps. cheers!
I disagree from #Mijail when he says
You cant not redirect with PHP in this case because the headers are not returned in the http response.
With jQuery (or plain XHR), you can verify if you got a redirection with the response status (one of 3xx) and then use getResponseHeader method from xhr object to get the 'location' header to see where you should be redirected :
success: function(data, textStatus, xhr) {
if(xhr.status > 300 && xhr.status < 400) {
document.location.href = xhr.getResponseHeader('location') || '/';
}
}
This is the right way of doing it when you don't want to replicate your redirection rules on the client side too.
In theory you could do it either way, but without seeing your actual code, it's hard to give a definitive answer.
If you are using jQuery to call your auth PHP script and setting your session in that PHP script, you would likely then just use your JS (Ajax) to redirect to the "protected" area on success (returned from your PHP script with session started).
Actually I am using ajax call and my code sample is here.. Please don't mind the syntax
$.ajax(
url: "mysite/action1",
success: function(resp) {
$("#divId").html(resp);
});
Like this I am loading the response text into one div tag. Now my problem is in zend controller I am trying to check for one condition like if session expired means redirecting to login page or else sending the response html code for that action.
public function action1Action() {
$login = new Zend_Session_Namespace('login');
if (isset($login->employee_id)) {
echo $html;
} else{
$this->view->headMeta()->appendHttpEquiv('refresh','1');
//$this->_helper->redirector->gotoUrl($this->view->baseUrl());
//$this->_helper->redirector('index', 'index');
}
}
I tried these three ways
$this->view->headMeta()->appendHttpEquiv('refresh','1'); -- Nothing happening
$this->_helper->redirector->gotoUrl($this->view->baseUrl()); and $this->_helper->redirector('index', 'index'); -- loads login page within the div tag (as it is taking as the ajax response)
I just want to reload the page. Just like triggering the browser refresh button to achieve what I want.. Please suggest any idea to solve my problem..
Note : I want to page reload from server side rather than checking in ajax response.. Is there a way to do it?
As you mentioned, you are trying to trigger "browser refresh", which is a frontend event. So I don't there you can do that in the backend.
It can be achieved using simple js code
window.location.reload();
When session expires just throw exception with proper HTTP code 401.
throw new Zend_Controller_Action_Exception('User not authorized', 401);
Then you can write global callback function for ajaxError and reload page or redirect user where you want.
$( document ).ajaxError(function(event, jqxhr) {
if (jqxhr.status === 401) {
window.location = '/'; // Use same base url here
}
});
You can take this one step further and write ACL plugin on preDispatch function to throw this exception. Then just ajdust little bit ErrorController so users are also redirected to login page and you will have consistent behavior for all requests, not only for XHR requests.
I have a password protected website--imagine something like linkedin-- where if the session expires you are prompted to log in again.
Some pages have ajax calls, however, that load content from the server into divs.
If you come back to the open div after the session expires and try to enter something, the php on the other end does a redirect within the div, and basically loads the whole login page inside the div. This creates a page within a page, an obvious error that tells the user, the site is not working properly.
Instead of the login page appearing inside the open div, I would like the div to close and the whole page redirect to the login. I am having trouble accomplishing this, however.
Right now I am doing the password protection with an include that checks for session and either allows you to continue or bumps you out to the login page.
If ($_SESSION['login'] != '1') {
header("Location: relogin.php"); }
I have this include in the scripts triggered by ajax calls to fill divs so users cannot bypass security. It is a catchall include that also holds some global variables, functions and so forth.
Can I add code that detects if call is coming from ajax or something so as not to do redirect and instead give message to login. Or ideally, close div and redirect whole page?
Because it is a large site, I would like to find one block of code that could go into the global include.
Would appreciate any suggestions.
You will need to do the redirect on the JS side.
Let's go over the PHP side first. You want to give your AJAX handlers a clear, unambiguous, stateful response: "sorry, you're not authorized". Let's borrow from REST a bit right?
Top of each of your AJAX calls:
<?php if (!YouAreLoggedIn()) {
header($_SERVER['SERVER_PROTOCOL']." 403 Forbidden");
exit(); ?>
This will throw the visitor a 403 error, and will kill the script. 403 errors in jQuery count as a XHR error, so you can map it independently of everything else.
Your typical AJAX call then becomes:
$.ajax({
url: "your.url.here.php",
type: "POST",
success: function(d) { YourSuccessCallHere(); },
error: function() { window.location.href='your.redirect.here.php'; }
});
This is the cleanest way to do it.
You could differentiate the two different calls by User-Agent or other header fields.
Use setRequestHeader() as described in links below:
JQuery Ajax Request: Change User-Agent
http://www.w3.org/TR/2007/WD-XMLHttpRequest-20070618/#dfn-setrequestheader
You could add a GET variable to the request URL whenever you're calling it via Ajax:
myurl.php?ajax=Y
Then on myurl.php, check to see if it's an ajax call:
if(!isset($_SESSION['login']) || $_SESSION['login'] != '1') {
if(isset($_GET['ajax'])){
echo json_encode("Please login!");
exit;
}
else{
header("Location: relogin.php");
exit;
}
}
Use the following header to check if the request was an AJAX request:
X-Requested-With: XMLHttpRequest
read the header in php using:
$_SERVER['HTTP_X_REQUESTED_WITH'];
Hey all I have a javascript function within a codeigniter view that retrieves some information from a codeigniter controller function that is acting strangely when the timeout for a user's session is reached. Within the called php function I have a statement that looks like this:
if (!$this->tank_auth->is_logged_in()) {
redirect(site_url('login'));}
This redirects them to my login page if they are not logged in. However in the javascript function I take the response text and set the contents of a div equal to it.
xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "mycontroller/myfunction/", false);
xmlhttp.send();
document.getElementById("mydiv").innerHTML=xmlhttp.responseText;
If the user is logged out when they call this function it will return the login page's responseText and insert it into the div instead of redirecting to the login page. This looks terrible. How can I stop it from doing this if the user session times out while looking at this page? I cannot change the timeout limit because other applications rely upon it.
Really this is not a codeigniter or tank_auth problem at all, simply how to redirect from a php function that is being called in an ajax request instead when I am originally using that function to generate a string for the responseText.
You need to parse the response and determine whether it is the type of response you're expecting. If you're expecting under a certain number of characters, you can check length, but that might not be as reliable as checking for specific dom objects or strings.
You could do, for example:
if(xmlhttp.responseText.length < 200) {
document.getElementById("mydiv").innerHTML=xmlhttp.responseText;
} else {
window.location.href = 'some url';
}
Another alternative would be to use CodeIgniter's AJAX response check to do something else instead of loading the view (or load a different view):
if ($this->input->is_ajax_request())
{
// do something else
}
else
{
// do what you were doing before
}
Hope this helps! I would shy away from doing the PHP/CI method because it sounds like you would be adding exceptions everywhere in your code which would not be pretty. It's totally up to you, though.
if you know your login design well. you can handle your response like this.
success: function (response) {
if(result.substring(0, 15) == '<!DOCTYPE html>') //Your login's HTML initials.
window.location = site_url_path + 'login'; //session timeout redirection.
//your normal functionality
}
It will be helpful when you have written redirection in a construct of your controller.
I have an index.html file which I want to run some jQuery when it is loaded. Essentially, I want to check to see if a user is already logged in based on some session variables.
So index.html will contain some jQuery which uses $(document).ready(function(){ });
In this function I want to just fire autheticate.php which checks to see if $_SESSION['user'] is set, if it is then it will redirect to home page otherwise it will redirect to login page...
how can I post in jQuery without having a html form? I just want to post to a url...
EDIT:
Based on #jondavidjohn's answer I changed my web app so that it uses index.php to check sessions:
<?php
session_start();
if(isset($_SESSION['username'])){
//go to home page
header('Location: ...home.html');
}else{
//go to login page
header('Location: ...login.html');
}
?>
It is surely possible doing this with javascript, but it is not secure at all...
You need to be checking at the server level for $_SESSION['user'] before you even send the content to the browser...
My answer would be to do the checking / redirecting with PHP before anything gets sent to the browser, it will be less complicated and more secure...
The reason a javascript solution is insecure is that you are relying on a technology that resides and is controlled by the client to control access to protected areas.
You can use $.post(url, params), where url is a string and params is a hash with your post data.
$.post("/authenticate.php",null,function(data){
// do something based on response returned
if($data){alert("authenticated");}
else
alert("not authenticated");
});
in your php file
if(isset($_SESSION['user']))
{
echo true;
}
else
return false;
Use $.post() to post data via AJAX to a page. Doing it this way won't allow the PHP script to redirect the user, you'll have to java JavaScript redirect them.
$.post('/path/to/page.php', {userID: 5}, function(data){
// Use window.location to redirect
});
Or, you can create a "fake" <form> element, and post that.
var $form = $('<form/>').attr({
method: 'post',
action: '/path/to/page.php'
});
var $input = $('<input/>').attr({
name: 'userID',
type: 'text'
}).val('5');
$input.appendTo($form);
$form.submit();
I suggest you take #jondavidjohn's advice, and have PHP redirect the user before the page is sent to the browser. That's much more secure.
Why bother with the AJAX request? Since you're building the page with PHP, just have PHP embed some variables in a JavaScript block:
<script type="text/javascript">
var is_logged_in = <?php echo $_SESSION['logged_in'] ? 'true' : 'false' ?>;
</script>
This'd save you an HTTP round-trip to retrieve data you already had available.