I have a web page, let's call it main.php which displays an image of football field and some players distributed on the field. However, that page uses list.php as a right side frame that loads a list of players.
What happens is, when the user clicks on a player on the field (main.php), let's say on the image of the Goal Keeper (GK), a list of GKs from world wide teams will load in right list fram (list.php). This is by using ajax.
So far we are good.
The current situation is, when session times out and the user clicks on a player from the field, the list on the right does not load, instead, list of players disappears from the list and a message says "Please login" is displayed on the right side frame (list.php)
The objective is, when session times out I want the whole website to redirect to the main page index.php
The problem is, I already put the redirecting code just before the code that is responsible of displaying the message "Please login". But what happened is, the redirection happens from within the frame, so i ended up having main.php displaying the field, and list.php displaying the main page!
Here's the code I added.
$user_id = NSession::get('user_id');
if (!isset($user_id))
{
NSession::removeall();
General::Redirect('index.php');
}
They are using Smarty. and btw, I added the same code to top of main.php, and now if user tries to access main.php without logging in, it will redirect him to the main page, so the code works!
n.b. The project is not mine, it belongs to the company I work in.
And I don't know which code is checking the session, all what I know is, if the user click on a player from the field after the session timeout, the "Please Login" message will be shown in the frame.
I'm guessing the redirect is essentially the same as using a header() function. It isn't possible to specify a target using a php redirect as it is server-side - specifying the target is client-side.
You would need to print something like this to the screen:
<script type="text/javascript">window.open('index.php','_parent');</script>
And that will redirect the user to the index.
Using frames for such purpose is... well... so 80ish...
Anyway, the frames are probably named in such a scenario. This means you can address them, but also that you have to address them. Just loading an url inside the "current" frame does exactly that, which is why your approach won't work.
If you really have to go with that frame based approach, then you will have to use javascript to address all known frames and redirect them.
Maybe you can use some javascript inside of your frame like so :
<script type="text/javascript">
window.top.location = 'YourPage.html';
</script>
Hope this helps
The issue was that the session expires while I'm on main.php. Therefore, any subsequent Ajax requested will fail since all requests requires session to be active.
the problem was that the Ajax request being sent from the IFrame (the IFrame is inside main.php and points to list.php thru Ajax calls) is failing due to session expiry.
So I've fixed this issue by adding another two session checks, one on main.php, list.php using PHP (check for session, if it's there, redirect). And in the main container, main.php, I check for the session via JS, interval Ajax requests to check the session, if session has ended, then use redirect using JS.
PHP:
$user_id = NSession::get('user_id');
if (isset($_POST["checklogin"]))//check loging
{
die(isset($user_id) ? "true" : "false");
}
if (!isset($user_id) || $user_id == "")
{
NSession::removeall();
General::Redirect('login.php');
}
JavaScript:
jQuery(document).ready(function($) {
$(window).focus(function() {
checkSession();
});
});
function checkSession()
{
$.ajax({
type: "POST",
data: {"checklogin": "cl"},
url: "list_players.php",
success: function(result) {
if (result === "false")
{
if (FIELD.showMessage === false)
{
FIELD.showMessage = true;
alert("Your session has been closed\nYou will be redirected to login page now. ");
window.location.href = ("login.php");//incase user clicks OK
}
}
}
});
}
Related
I am using joomla 1.5. I have a separate code which is in the same domain but in an another folder. I am accessing that folder within my joomla code by making use of iframe. Now I have to send the session value from joomla application to iframe and I am doing that by the following code.
echo '<iframe src="https://localhost/demo/quiz/quiz_main.php?u_d='.$user->id.'" width="910" height="885" style="background-color:transparent"></iframe>';
where $user->id is the registered user'd id and obviously this page will open if user logs in.
Then in the quiz_main.php page I am checking the value of u_d and according to that I am controlling the system.
Now the problem is suppose, I opened two tabs in the same browser with the same url and log in with same user id. Now log out from one tab. Then go to the other tab. User can perform any action for that small application which is running inside the iframe, until the page is not refreshed . But it should not be.
Please help me how to fix this issue.
You have to perform the check server side anyway, so in quiz_main.php you'll need something like
<?php
if(!user_is_logged_in())
// Redirect to login
?>
To prevent the user from performing any actions that will affect data on the server.
You can also do a check client side using JavaScript. You can poll the server every n seconds to check if the user still is logged in, and if not redirect the user to the appropriate page.
Example below with jQuery
function logged_in() {
$.ajax({
url: '/logged_in.php',
type: 'post',
success: function(data) {
data = $.parseJSON(data);
if(data['logged_in'] != true)
window.location('login.php');
else
setTimeout('logged_in()', 5000); // calling itself in 5 seconds.
}
});
}
$(document).ready(function() {
logged_in(); // Calling first time when the document is ready.
});
Just a rough sketch on how this could be done. You'll need a logged_in.php to handle to your request of course.
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'];
I have this simple login script:
$.ajax({
type: 'POST',
url: 'authorize.php',
data: { username: user, password: pass },
dataType: 'json',
success: function(data) {
if (data.status == "loggedIn") {
//Logged in
} else {
//Not logged in
}
}
});
Where //Logged in is, how should I call the page that required the login? I could simply $.load the page, but then what was the point of verifying a login when the user could just browse to this file in the first place?
I'd suggest using PHP Sessions across all of these pages. Make a check on the page you're going to $.load that the user is actually logged in and set the user as logged in on the authorize.php page if successful.
This way, if a user looks at the page source and see's what you're loading, but when they try and access that page it won't do anything because you're checking to see if they've been logged in already.
It's a matter of presentation, you can just load a div on another file, you don't need to load the whole thing.
I use ajax to login and $.load to "bring" a div I have in a template file. It's just because it makes it easier when you need to change the design.
Remember that splitting the work into individual "pieces" makes it easier for you to change things. Imagine you have the same login box on 20 individual templates. If you change one, you have to change 19 more.
You can't prevent a user from doing anything with javascript (jquery), since it is client-side and easily disabled/changed etc.
What you can do is simply $.load the page like you say, but also have a check against the session on the loaded page that checks for an actual login before sending the content. You'd need to set some variable in the session as part of authorize.php to indicate a successful login.
To prevent data from being accessed, you should look into using .htaccess and Apache's mod_rewrite. Whenever a user requests a piece of possibly sensitive data, you'll invisibly call a PHP page which will then serve up either the requested data or a 403 Forbidden.
Example:
.htaccess
RewriteEngine On
RewriteRule ^user-content/(.+) display_content.php?file=$1
Then, any files that would be accessed in user-content will be rerouted through display_content.php. You can also use this .htaccess file to help prevent hotlinking by refusing to display the resource if there's a referrer.
display_content.php
<?php
if (isLoggedIn($_COOKIE["username"], $_COOKIE["password"]) && isset($_GET["file"])) {
if (mimeTypeOk($_GET["file"]) { // Implementation not shown
readfile($_GET["file"]);
exit();
}
}
header("403 Forbidden");
?>
In order to do this the most secure way, you are going to have to use both jQuery as a client-side way and PHP as a server-side way of checking if the user is logged in. You don't need to load the entire page with jQuery, just use the following code to load only a div portion:
$("#load_dom").click(function(){
$("#result")
.html(ajax_load)
.load(loadUrl + " #picture");
});
Then, as a security measure, use PHP to restrict access to the page, by checking $_SESSION vars like this:
if (!isset($_SESSION['userid'])) {
// user is logged in
} else {
// user is not logged in
die("You are not logged in.");
}
How do I clean information in a form after submit so that it does not show this error after a page refresh?
See image (from chrome):
The dialog has the text:
The page that you're looking for used
information that you entered. Returning to that
page might cause any action you took to be
repeated. Do you want to continue?
I want this dialog not to appear.
This method works for me well and I think the simplest way to do this is to use this javascript code inside the reloaded page's HTML.
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
Edit: It's been a few years since I originally posted this answer, and even though I got a few upvotes, I'm not really happy with my previous answer, so I have redone it completely. I hope this helps.
When to use GET and POST:
One way to get rid of this error message is to make your form use GET instead of POST. Just keep in mind that this is not always an appropriate solution (read below).
Always use POST if you are performing an action that you don't want to be repeated, if sensitive information is being transferred or if your form contains either a file upload or the length of all data sent is longer than ~2000 characters.
Examples of when to use POST would include:
A login form
A contact form
A submit payment form
Something that adds, edits or deletes entries from a database
An image uploader (note, if using GET with an <input type="file"> field, only the filename will be sent to the server, which 99.73% of the time is not what you want.)
A form with many fields (which would create a long URL if using GET)
In any of these cases, you don't want people refreshing the page and re-sending the data. If you are sending sensitive information, using GET would not only be inappropriate, it would be a security issue (even if the form is sent by AJAX) since the sensitive item (e.g. user's password) is sent in the URL and will therefore show up in server access logs.
Use GET for basically anything else. This means, when you don't mind if it is repeated, for anything that you could provide a direct link to, when no sensitive information is being transferred, when you are pretty sure your URL lengths are not going to get out of control and when your forms don't have any file uploads.
Examples would include:
Performing a search in a search engine
A navigation form for navigating around the website
Performing one-time actions using a nonce or single use password (such as an "unsubscribe" link in an email).
In these cases POST would be completely inappropriate. Imagine if search engines used POST for their searches. You would receive this message every time you refreshed the page and you wouldn't be able to just copy and paste the results URL to people, they would have to manually fill out the form themselves.
If you use POST:
To me, in most cases even having the "Confirm form resubmission" dialog pop up shows that there is a design flaw. By the very nature of POST being used to perform destructive actions, web designers should prevent users from ever performing them more than once by accidentally (or intentionally) refreshing the page. Many users do not even know what this dialog means and will therefore just click on "Continue". What if that was after a "submit payment" request? Does the payment get sent again?
So what do you do? Fortunately we have the Post/Redirect/Get design pattern. The user submits a POST request to the server, the server redirects the user's browser to another page and that page is then retrieved using GET.
Here is a simple example using PHP:
if(!empty($_POST['username'] && !empty($_POST['password'])) {
$user = new User;
$user->login($_POST['username'], $_POST['password']);
if ($user->isLoggedIn()) {
header("Location: /admin/welcome.php");
exit;
}
else {
header("Location: /login.php?invalid_login");
}
}
Notice how in this example even when the password is incorrect, I am still redirecting back to the login form. To display an invalid login message to the user, just do something like:
if (isset($_GET['invalid_login'])) {
echo "Your username and password combination is invalid";
}
It has nothing to do with your form or the values in it. It gets fired by the browser to prevent the user from repeating the same request with the cached data. If you really need to enable the refreshing of the result page, you should redirect the user, either via PHP (header('Location:result.php');) or other server-side language you're using. Meta tag solution should work also to disable the resending on refresh.
After processing the POST page, redirect the user to the same page.
On
http://test.com/test.php
header('Location: http://test.com/test.php');
This will get rid of the box, as refreshing the page will not resubmit the data.
It seems you are looking for the Post/Redirect/Get pattern.
As another solution you may stop to use redirecting at all.
You may process and render the processing result at once with no POST confirmation alert. You should just manipulate the browser history object:
history.replaceState("", "", "/the/result/page")
See full or short answers
You could try using AJAX calls with jQuery. Like how youtube adds your comment without refreshing. This would remove the problem with refreshing overal.
You'd need to send the info necessary trough the ajax call.
I'll use the youtube comment as example.
$.ajax({
type: 'POST',
url: 'ajax/comment-on-video.php',
data: {
comment: $('#idOfInputField').val();
},
success: function(obj) {
if(obj === 'true') {
//Some code that recreates the inserted comment on the page.
}
}
});
You can now create the file comment-on-video.php and create something like this:
<?php
session_start();
if(isset($_POST['comment'])) {
$comment = mysqli_real_escape_string($db, $_POST['comment']);
//Given you are logged in and store the user id in the session.
$user = $_SESSION['user_id'];
$query = "INSERT INTO `comments` (`comment_text`, `user_id`) VALUES ($comment, $user);";
$result = mysqli_query($db, $query);
if($result) {
echo true;
exit();
}
}
echo false;
exit();
?>
I had a situation where I could not use any of the above answers. My case involved working with search page where users would get "confirm form resubmission" if the clicked back after navigating to any of the search results. I wrote the following javascript which worked around the issue. It isn't a great fix as it is a bit blinky, and it doesn't work on IE8 or earlier. Still, though this might be useful or interesting for someone dealing with this issue.
jQuery(document).ready(function () {
//feature test
if (!history)
return;
var searchBox = jQuery("#searchfield");
//This occurs when the user get here using the back button
if (history.state && history.state.searchTerm != null && history.state.searchTerm != "" && history.state.loaded != null && history.state.loaded == 0) {
searchBox.val(history.state.searchTerm);
//don't chain reloads
history.replaceState({ searchTerm: history.state.searchTerm, page: history.state.page, loaded: 1 }, "", document.URL);
//perform POST
document.getElementById("myForm").submit();
return;
}
//This occurs the first time the user hits this page.
history.replaceState({ searchTerm: searchBox.val(), page: pageNumber, loaded: 0 }, "", document.URL);
});
I found an unorthodox way to accomplish this.
Just put the script page in an iframe. Doing so allows the page to be refreshed, seemingly even on older browsers without the "confirm form resubmission" message ever appearing.
Quick Answer
Use different methods to load the form and save/process form.
Example.
Login.php
Load login form at Login/index
Validate login at Login/validate
On Success
Redirect the user to User/dashboard
On failure
Redirect the user to login/index
Hope you can help. A bit of a jQuery/AJAX newb here.
I have a basic SimpleModal login form that may be called from the homepage of my site.
login.js calls the login.php script that checks my database for a user's credentials.
If the login is successful I set a few session variables and I usually use the header command to send the user to their personal page (or the error page on login failure).
eg. header("Location:restricted/index.php");
I can't get the modal login form to close and the parent homepage to redirect to the member page. I'm usually left with the blank modal square saying "Thank You"
If i try to close the modal form with
success: function (data) {
$('#login-container .login-loading').fadeOut(200, function () {
$('#login-container .login-title').html('Thank you!');
msg.html(data).fadeIn(200);
$.modal.close(); //have inserted this line
});
},
the modal closes but I am left on the homepage. (The user is logged in at this stage but the redirect has not happened).
I've been kicking this around for a day or 2. I had a look at the wordpress login plugin but I am none the wiser. Any ideas?
Actually the redirect probably did happen, it just happened inside the AJAX request. When you do a redirect, the XmlHttpRequest that the ajax functions use transparently follows it, so then page that came back to the client is the restricted/index.php. what I tend to do is add a header on that page, something like this:
header("Redirect:restricted/index.php");
Then look for the header, something like this using $.ajaxSetup():
$.ajaxSetup({
complete: function (xhr) {
var redirect = xhr.getResponseHeader('Redirect');
if(redirect) window.location.href = redirect;
}
});
This way (unless you override complete, it leaves this option open) when a request comes back that made it to the restricted/index.php (remember the XmlHttpRequest actually went there) it'll get a header to let the client know it needs to redirect.