How could I check if a user has left my login form? Not logging in but actually leaving it?
As I want to delete the Auth.redirect session if they choose not to login so that when they return later they are not taken to their previous session!
So essentially running this:
$this->Session->delete('Auth.redirect');
I'm thinking some kind of check in the AppController that knows when a user was referred from the login form and deletes the session auth.redirect???
Or better yet checking if the current page is the login form and if not then delete the session!!!
and for those that are interested, this is how my login method currently looks:
function login()
{
if(!(empty($this->data)) && $this->Auth->user())
{
$back_to = $this->Session->read('back_to');
$auth_redirect = $this->Session->read('Auth.redirect');
if($auth_redirect)
{
$this->redirect($auth_redirect, null, true);
}
else if($back_to)
{
$this->redirect($back_to, null, true);
}
else
{
$this->redirect($this->Auth->redirect(), null, true);
}
}
else
{
$this->Session->write('back_to', $this->referer());
}
}
Thanks
I am not familiar with CakePHP but your question sounds a bit strange to me. You are talking about PHP, a server side scripting language. A PHP script gets executed only when a request comes in (please correct me if there is something I don't know yet).
So, when a user calls the login page, the script gets executed. Now think of the following: Just after the login page has been loaded, the user closes the browser-tab with the login page. This does not trigger a request, so there is no possibility to inform the server about that action.
Maybe CakePHP can do such magical things, but I think we are talking about stateless HTTP, so I can't imagine how to realize something like that.
You could add a timestamp to the session of when you have last received a request from the user. For example, in AppController::beforeFilter, just add $this->Session->write('lastSeen', time()). You can then check how much time elapsed between the last time the user opened any page, and discard the Auth.redirect value if that interval was too long.
That's basically the same as expiring the session, just in a more controlled fashion. If you want to count the time a user simply has your page displayed on his screen as "activity" as well, you can use some Javascript AJAX to keep sending requests to the server to signal "I'm active!"
That's all quite a lot of work for very little benefit though. HTTP is stateless and doesn't allow you to track the user easily, period. Actually tracking whether a user is "actively" watching your page or not incurs a huge overhead and in this case seems like misplaced effort for the extraordinarily narrow purpose you want to use it for.
if($this->here != '/admin/login')
{
$this->Session->delete('Auth.redirect');
}
or this:
if($this->here != Router::url(array('admin'=>true,'controller'=>'users','action'=>'login')))
{
$this->Session->delete('Auth.redirect');
}
Related
I dont really have much experience in cache controlling and CakePhp. I am not a regular programmer as well. I got a situation where if the user is visiting a site for a first time there will be a pop up appearing on the screen. If the user visited it before there wont be any popup.
As for checking the user is authentic, i can use
<?php if (empty($auth_user)) { ?>
//codes for popup modal
<?php } ?>
My question is, is that possible to implement some logic like this to catch the cache or check wheather the tmp file is empty or not?
No there is not good ways to catch cache, But there only one way COOKIES to do it but it will be terminated and work newly as user just delete them in his browser.
As php is an server side scripting language
If you not want to save cookie then use LOCALSTORAGE but in JAVASCRIPT
1.COOKIE(Cookies can be stored via PHP)
setcookie(nameOfCookie, valueOfCookie, expireTimeOfCookie, pathOfCookie);
Simple insert "/" in pathOfCookie
Getting COOKIE in PHP
<?php
if(isset($_COOKIE[$nameOfCookie])) {
//User already visited your site.
} else {
//Use doesn't visited your site yet.
//Show POPUP here. And set cookie here (In Else Condition).
}
?>
Keep in mind that if the expiryTimeOfCookie passes it will expiry. And not exist (Time In Seconds For 1 Day = 86400
Looking for help. I am new to the ob_start and believe I'm not using this correctly as users are sent back to my load-data.php after browsing my website without cause. I've paid very close attention to each page that is loaded, and it looks like there is something kept on the client that get's reposted? The code I use loads FB data, then based on whether a new user, or existing user I redirect using this code...
ob_start();
...Load FB Data then
if(isset($_SESSION['user_id']) && $isNewUser == 0)
{
header('Location:loading-data.php?x=4');
exit();
}
else
{
$_SESSION['user_id'] = $user_id;
This 'loading-data.php' is called a number of times for some users and I'm not sure why, but have a feeling that there is something in the buffer on the client's machine that reposts stacked memory? What is the best coding technique to insure it doesn't get posted more than once?
I am attempting to set a cookie and then check to see if the cookie has been set.
So in one function, I have it make the cookies:
public function makeCookies(){
Cookie::queue('logged_in', $value, 15);
Cookie::queue('user_id', 2);
//return Response::make()->withCookie(Cookie::make('logged_in', $value, 15))->withCookie(Cookie::forever('user_id', 2));
}
And in the other function, I try to check to see if the cookie has been set:
public function checkCookies(){
$this->makeCookies();
if(Cookie::get('logged_in') && Cookie::get('user_id')){
return 'Logged In!';
}
}
However the only way this works is if I add 'return' before $this->makeCookies(); However, I want to be able to get to the conditional below it. Is there any way I can go about doing this? Any help is greatly appreciated.
To understand the Cookie Creation/Read process:
The user's browser sends a request for a page, along with any cookies that it currently has for the site
The site serves up the page, and any cookies you create become a header in your response.
Subsequent requests to your site will send the cookies created in #2.
What you are asking...to be able to read cookies that you create in step #2 in step #1...not possible.
Now, depending on how the Cookie class is created, you could make it so that when the Cookie::queue() is called, that it creates in-memory data that reflects what the cookie "should be" on the next request, but it doesn't truly know whether or not the user's browser will accept cookies, etc.
This is why many sites, after creating a cookie give the user a redirect to a page with something like ?checkCookie=1. This way, on the subsequent request, they can verify that your browser supports cookies...and if the cookie doesn't exist on the ?checkCookie page, they give you an error saying that their site requires cookie support. However, it does require a second round to the server to read cookies from the browser that were created.
UPDATE 2015-04-24 Per #Scopey, Laravel does support in-memory retrieval of cookies via queued(). So, you should be able to do:
public function checkCookies(){
$this->makeCookies();
$loggedIn = Cookie::get('logged_in') ?: Cookie::queued('logged_in');
$userId = Cookie::get('user_id') ?: Cookie::queued('user_id');
if( $loggedIn && $userId ){
return 'Logged In!';
}
}
SECURITY CONCERNS (NOT DIRECTLY ANSWERING THE QUESTION)
Your question was only about the cookies, so that's all I answered. However, now that I'm looking at your code, I feel I would be remiss not to point this out for anyone that happens to be reading this. This may just be a "how to" for yourself and not production code, but that code could be very dangerous if it ever went public.
Make sure you do NOT TRUST a user_id stored in a cookie to determine what user is coming in via cookies. If you rely on that, and I come to your site, I can modify my cookie to any user_id I want and get into other people's accounts.
General Safety Rules:
A cookie should contain a GUID, or similar random string to identify the session. This random string should be sufficiently long (e.g. 32 characters or greater, IMHO) that it is not easy for someone to brute-force their way to hijacking sessions.
The user_id should be stored in the $_SESSION (or laravel's wrapper for session if applicable) so that the user doesn't have any access to the user_id to be able to modify it.
In plain PHP, this something like this for the login page:
session_start();
if( isValidPassword($_POST['username'], $_POST['password']) ) {
$_SESSION['user_id'] = $user->Id;
}
else {
die('invalid login credentials');
}
The session_start() method automatically generates a cookie for the user with that long, random string (so you don't even have to worry about that part.)
On subsequent pages, you just check the session user_id to know who is logged in:
session_start();
if( empty($_SESSION['user_id']) ) {
die('You are not logged in and cannot access this page');
}
Change as needed per Laravel's documentation, which if they have their own session wrapper, I'm sure is well documented on best practices.
Excellent description by #KevinNelson about cookies but Laravel does support fetching back any cookies you have queued in the current request. Try using
Cookie::queued('logged_in');
The catch is, the cookie will only be "queued" during the request that you queued it. You will have to use get like you are for any other requests.
im using a script from here: http://www.php-login.net
I altered it to suit my own needs but i see this part in the script:
// if user has an active session on the server
elseif (!empty($_SESSION['user_name']) && ($_SESSION['user_logged_in'] == 1)) {
$this->loginWithSessionData();
// checking for form submit from editing screen
if (isset($_POST["user_edit_submit_name"])) {
$this->editUserName();
} elseif (isset($_POST["user_edit_submit_email"])) {
$this->editUserEmail();
} elseif (isset($_POST["user_edit_submit_password"])) {
$this->editUserPassword();
}
I am not too sure how session variables work since there on the server and technically they cant be altered directly however this part of the code shows it can be altered indirectly if someone messed with cookies.
private function loginWithSessionData() {
$this->user_name = $_SESSION['user_name'];
$this->user_email = $_SESSION['user_email'];
// set logged in status to true, because we just checked for this:
// !empty($_SESSION['user_name']) && ($_SESSION['user_logged_in'] == 1)
// when we called this method (in the constructor)
$this->user_is_logged_in = true;
}
Im not sure if its possible but if i messed with the cookies and set username=x and got lucky and set is_logged_in as 1 could that give the user access? Im sure there is a much safer method of validating a session or do cookies themselves also come with there own type of validation like checking the machine hash and that hash must also match with the hash we stored on the server? Instead of something as simple as user_logged_in should i use a random string called it iftodaywasarainyday and just comment it internally so i know what that value corresponds with my is_logged_in or does it even matter.
I will do some more reading up on the subject but i guess i took the authors word for it since the first 3 words on the page are "A simple, clean and secure" and the site does look quite good but as i was refactoring the code there is lots of todo statements which got me worried its work in progress rather than a finished script
Session data is stored server-side. The actual data isn't in the cookie at all. The cookie is just an ID that let's the server know which session data to load. Users cannot modify this session data unless you allow them to by writing code that does it.
I might not have known what to search for to get this answer so please point me to the correct post if this has been dealt with already.
Now then, I have a little custom CMS and I want to ensure users don't re-submit their $_POST data by refreshing the page. So I've done something like this:
<?
//Start a session to hold variables I want after my redirect
session_start();
if($_POST){
//Do some php stuff and if I'm happy with the results...
$_SESSION['some_vars'] = $whatever;
//Bring me back here but without the $_POST data
header('Location: '.THIS_PAGE);
exit;
}
?>
When the script reloads I use my session variables and trash the session.
I'm wondering if anybody has a better way to handle this. It's fairly non cumbersome but I'm always looking for more efficiency.
Thanks.
EDIT: By the way, stackoverflow.com does this somehow when you post a question if what I'm doing seems unclear, but they also make a permalink while they're at it.
You have actually implemented what is called the Post-Redirect-Get pattern, and it is absolutely a correct way to do this. I do this myself. I use it so often, I usually implement some minor helper functions into my base controller classes to help me use it:
public function prgRedirect($url = null, $sessionData = null)
{
if ($sessionData !== null) {
if (! isset($_SESSION)) session_start();
$_SESSION['_PRG'] = $sessionData;
}
if ($url === null) $url = $_SERVER['HTTP_REFERER'];
header("Location: ".$url);
}
public function getPrgData()
{
if (! isset($_SESSION)) session_start();
if (isset($_SESSION['_PRG'])) {
$data = $_SESSION['_PRG'];
unset($_SESSION['_PRG']);
}
else {
$data = null;
}
return $data;
}
I usually use it with REST-style URLs, so a POST request will do whatever it has to do, save some data to session using prgRedirect(), which then redirects back to the GET url for the same resource/page. The handler for the GET method will call getPrgData() at the top of the execution and see if there's anything in the session data.
if its important that user dont insert the same data I'm sure there must be some unique column in your database (like headline maybe?). so just check if this headline already exists. you wont need to use any sessions that way
What about:
1. Generate random string (uniqid or md5)
2. Store it in session and put in into hidden input at the form
3. Check form value and session value - if it matches - process the form. Clear the session value.
There are actually two problems here:
users hitting the refresh button in their browser when the data is already saved and you are in a page which saves the data
user hits the "back" button in the browser and clicks "submit" button once again.
In the first scenario, the best scheme is to follow the GET-after-POST pattern where you use the header("location:somewhere_else.php") call to redirect the user. This way you do not have to worry about being called two times consecutively, since the page where you posted the data, is not in the browser's history list (because the server had returned 302 header).
The second scenario hurts a bit more, because the GET-after-POST does not help. If the user submits the form twice, the you may save the data twice. In this case, there may be several solutions:
put a "form identifier" (a random string) in every form you send to the client. When client submits the form, check if you already have such identifier in session data. If you don't have it, save form data and remember the identifier in user's session as "already used". If you find the identifier in session data, don't save anything - it's a duplicate.
check the database for exactly the same values that are submitted. If they match, do not save a duplicate. However, the user may have clicked "back" button, changed some piece of data and then re-submitted the form.