I have a controller called Accounts, with the views signin and signout.
The corresponding functions look like this:
function signin()
{
if (!empty($this->data))
{
//handle login
...
//save login to session
$this->Session->write('Account', $data["Account"]);
//redirect to previous page
???
}
}
function signout()
{
//delete login
$this->Session->delete('Account');
//redirect to previous page
???
}
If the user goes to accounts/signin it first checks to see if the form is submited if(!empty($this->data)) if yes, it logs them in, if not it renders the signin form. If they do succesfully log in, I want to redirect them to the page they were at before the signin page.
Whats the best way to do that?
Edit:
I do not think I can user a regular http referrer because technically the referrer will always be the signin in page because they go to /signin, then submit the sign in form. So at the point where the form is submited the referrer is always /signin. I want to redirect to where they were before that. Does that make sense?
the best way is to use cakes Auth component and let it do what it does... http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#AuthComponent::$loginRedirect
Here's how I do it with referer
I have 2 login forms, one is a form at the top of all pages for easily sign in, the other is on login action. If the user comes in using the form at the top, the form submission then goes to login page and you can use $this->referer() to redirect the user back.
But the problem is that, if the user types the password wrong or enter invalid credential, he will then end up on the login page. If he then enters the right username+password, and redirection occurs using $this->referer(), which in this case is itself. The user then could then either 1. get redirected back to login page again or 2. even worse can get stuck in an infinite loop b/c login will keep redirecting to itself.
So, I add some logic to check to make sure that referer is not login page. Also, I add another logic to store $this->referer() the first time the user lands on login page, we we know where exactly the page before login page.
To store the page before login page, put this code at the end of the action (login view rendering is about to begin)
//get the current url of the login page (or current controller+action)
$currentLoginUrl = strtolower( "/" .$this->name ."/" .$this->action );
if( $this->referer() != $currentLoginUrl )
{
//store this value to use once user is succussfully logged in
$this->Session->write('beforeLogin_referer', $this->referer($this->Auth->redirect(), true)) ) ; //if referer can't be read, or if its not from local server, use $this->Auth->rediret() instead
}
Now put the code to redirect in the part of the code where authentication is succesful (or in if( $this->Auth->user() ){ } ):
//get the login page url again (by gettting its controller, or plural of Model, and this current page action and make the url)
$currentLoginUrl = strtolower( "/" .$this->name ."/" .$this->action );
//if the referer page is not from login page,
if( $this->referer() != $currentLoginUrl )
{
//use $this->referer() right away
$this->redirect($this->referer($this->Auth->redirect(), true)); //if referer can't be read, or if its not from local server, use $this->Auth->rediret() instead
}
else
{
//if the user lands on login page first, rely on our session
$this->redirect( $this->Session->read('beforeLogin_referer') );
}
Hope this works for you.
http://book.cakephp.org/view/430/referer
Use a hidden <input> field that holds the initial referrer and gets submitted with the login data.
I don't know about the best way, but I store the attempted destination in a session variable before redirecting them to the sign in page.
Once they have signed in, I redirect them to the stored destination.
Use the AppController and UsersController to set it up
In AppController beforeFilter action
$referer = Router::url($this->url, true);
$this->Auth->loginAction = array('controller'=>'users','action'=>'login','?'=>['referer'=>$referer]);
In UsersController login action
if($this->Auth->login())
{
$this->Session->setFlash(__('Logged in successfully !'));
$redirect = $this->request->query('referer');
if(!empty($redirect))
{
return $this->redirect($this->Auth->redirectUrl($redirect));
}else{
return $this->redirect($this->Auth->redirectUrl());
}
}
CakePHP 2.x here
1. Edit AppController.php
public function beforeFilter() {
// redirect url
if($this->request->here!= '/users/login') {
$user_id = AuthComponent::user('id');
if(empty($user_id)) { $this->Session->write('redirect_url_after_login', Router::url($this->request->here, true)); }
}
This will store the url the user wanted to go before request, only if the url is not /users/login (replace with your url of login) AND if no user is logged.
2. Edit your login form. Mine was Users/login.ctp. Add an hidden field only if there is a session variable set.
$redirect_url_after_login = $this->Session->read('redirect_url_after_login');
if(!empty($redirect_url_after_login))
echo $this->Form->input('redirect_url_after_login', ['value'=>$redirect_url_after_login, 'type'=>'hidden']);
3. In your login action, add an action to overwrite the loginRedirect variable you may have set before.
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$redirect_url_after_login = $this->request->data['User']['redirect_url_after_login'];
if(!empty($redirect_url_after_login)
&&filter_var($redirect_url_after_login, FILTER_VALIDATE_URL)
&&parse_url($redirect_url_after_login, PHP_URL_HOST)==$_SERVER['HTTP_HOST'])
return $this->redirect($redirect_url_after_login);
$this->Session->delete('redirect_url_after_login');
return $this->redirect($this->Auth->redirect());
}
I added a couple of security checks, like "is the redirect url a valid url?" and "is it redirecting towards my domain or an external domain?".
Note: I know checking $_SERVER['HTTP_HOST'] is not bulletproof, but here we're talking about preventing open redirect vulnerability, so it's enough.
Related
I have tried many different things to get this to work and this is what I currently have:
// save the redirect_back data from referral url (where user first was prior to login)
$this->session->set_userdata('redirect_back', $this->agent->referrer() );
// user is authenticated, lets see if there is a redirect:
if( $this->session->userdata('redirect_back') )
{
$redirect_url = $this->session->userdata('redirect_back'); // grab value and put into a temp variable so we unset the session value
$this->session->unset_userdata('redirect_back');
redirect($redirect_url, 'refresh');
}
else
{
redirect('/', 'refresh');
}
The problem with this is sometimes there is no referral url. For example I allow video/image uploads. If the user is on the home page page and they click on the upload videos button and they're not logged in it redirects them to the log in page and refreshes and there is no longer a referral url. I want the user to be redirected back to the upload videos page because they tried to access this page but could not because they were not logged in.
Does any know why this is happening?
You can solve this in the constructor for each controller of the logged in areas. For example:
public function __construct() {
parent::__construct();
/*
* First check to see if they are logged in
* if not redirect to login in page with
* redirect back information
*/
if (!$this->session->userdata('uid')) {
redirect(base_url() . 'login?ref=account');
} else {
/*
* if they are logged in, load helpers, models, libs
* and proceed with viewing normally
*/
$this->load->helper('form');
$this->load->library('form_validation');
//etc.
}
}
I use a query string here but you can just as easily use uri segments. The login controller then picks up the query string and upon successful login, uses it to send them back. The advantage is they always redirect back to where you want them to go, because you always know where they were based on your explicit code. The disadvantage is its a little more maintenance since you have to make sure all you "protected" areas have the appropriate redirect parameters. You can make this more flexible using current_url() as was mentioned in the comments. You also have to deal with data in the url which the user can mess with, but if you've designed everything else correctly, that shouldn't be much of an issue. I like this method because it explicitly keeps me in control of flow and I can adjust each controller to go where I want and return to where I want.
I am using CakePHP 2.2.0, When a user is not logged in, when a link is clicked, it goes to the login page, after login i would like to redirect to the initial link that was clicked. Anybody knows how we can implement it using CakePHP? I tried with the $this->referer() but it seems not getting the previously visited URL. If anybody knows please help me to sort out!
If you need to redirect to the referer page you can use:
$this->redirect($this->referer());
Reference: http://book.cakephp.org/2.0/en/controllers.html#flow-control
In the method processing the login, you could redirect to
$this->Auth->redirectUrl()
This should work:
if ( $this->Auth->login() ) {
return $this->redirect( $this->Auth->redirect() );
}
From the doc:
The above code (without any data passed to the login method), will
attempt to log a user in using the POST data, and if successful
redirect the user to either the last page they were visiting, or
AuthComponent::$loginRedirect. If the login is unsuccessful, a flash
message is set.
if ($this->Auth->login()) {
$this->Session->write('SESSION_DATA_HERE', 1);
return $this->redirect( $this->Auth->redirect() );
} else {
$this->Session->setFlash("Username or Password is incorrect.Please try again.", 'error');
$this->redirect($this->referer());
}
Validate Auth User, if tru then redirect to the last visit page otherwise to the login screen from which user logged in by providing username and password
Actually, you can do this by adding some back_url to your Log In link and then you can use that value for redirecting users.
Something like this:
<?php
// log in link
echo $this->Html->link('Log In', '/login?back_url='.$_SERVER['REQUEST_URI']);
// log in action
$back_url = $this->request->query('back_url');
if($back_url === null) $back_url = '/';
// ... some other code
if($this->Auth->login()) {
$this->redirect($back_url);
}
?>
I'm currently learning the basics of MVC using codeigniter as my framework and I created a login page. Now I already redirected a user after he logged in and stored a session data but the problem is after I log in (where in I redirected into another page) then pressed the back button the login page still displays unless I highlight the URL in the address bar and pressed enter wherein I go back again to the redirected page. Well I'm aware that this is because of the session check I've made but I need a solution on how I can solve it for the user to not go back again to login page unless he logged out. Same thing for logged out user not to go back to a certain page unless he/she logs in again.
To give a more details what exactly I wanted to happen is just like in facebook login wherein after you logged in and clicked the back button on browser the facebook will still redirect you to your homepage and not on the login page. samething goes to logout.
Well here's my controller so far I think this explains it all. Please do correct me if I made some redundancies in my code and understand that I'm a newbie on this. :)
public function index()
{
$data['error'] = null;
$username = $this->input->post('username');
$password = $this->input->post('password');
$data['login'] = $this->login_model->get_login_credentials($username,$password);
$data['session'] = $this->login_model->get_session($username);
//CHECK IF THE $PAGE VIEW IS EXISTING
if ( ! file_exists('application/views/pages/login.php'))
{
// IF PAGE DOESN'T EXISTS SHOW 404 ERROR
show_404();
}
if(($this->input->post('login')=='Login'&&$data['login']==1)||($username==$data['session']['username'])){
//SUCCESS LOGIN
$this->load->helper('url');
redirect('news');
}
if($this->input->post('login')=='Login'&&$data['login']!=1){
//LOGIN FAILED
$data['error'] = "Invalid login credentials.";
}
//FOR THE TITLE PART
$data['title'] = ucfirst('login');
$this->load->view('pages/login/login', $data);
$this->load->view('templates/footer', $data);
}
First for checking session data you can use :
$this->session->userdata('item');
here
$username==$data['session']['username'])
And perhaps you can SET 1 check at the start of your index as :
if($this->session->userdata('username'))
redirect('news');
Dont forget to load all helpers and libs required before callign those functions..
For sessions check http://codeigniter.com/user_guide/libraries/sessions.html
If you don't want to to go to login page after successful login, you can test the session in login page and redirect into some other page if session is set. Try this code.
if ($data['session']['username']) != NULL) {
redirect('home_page','refresh');
}
This question is already solved here: Clear cache on back press to prevent going back on login page or previous page after logout by Hashem Qolami Same question but in different perspective.
I have a login page that when you login in successfully you will be redirected to a page called gallery.html. However, when you type in the url with /gallery.html it will take you to the page that im trying to secure with logging in. What's the best way to use a conditional statement to prevent the page from being opened by typing in the exact URL? like a check before the page starts to load,
Simple, Use session variable on log-in, redirect the user to gallery.html if the session id is set, otherwise redirect to login page, something like this
if($_SESSION['userid']){
header( 'Location: gallery.html' ) ;
exit();
}elseif($_SESSION['userid'] == ''){
header( 'Location: login.html' ) ;
exit();
}
I like to create a function to handle this kind of thing:
function loggedin() {
if ( isset($_SESSION['user_id']) ) {
return true;
} else {
return false;
}
}
Or something shorter using a ternary operator:
function loggedin() {
return (isset($_SESSION['user_id'])) ? true : false;
}
Now to make the check, simply call the function within an if statement:
if ( loggedin() ) {
// only logged in users can see this
}
OR
if ( !logged_in() ) {
// only users who aren't looged in can see this
}
Much easier than typing something like if (!isset($_SESSION['user_id'])) { every time!
if you want to not show gallery.html to anonymous user, use this code at top of page
if(!isset($_SESSION['your_user_login_id']))
{
//redirect to home page
}
this code will prevent from anonymous user to view this page.
Use $_SESSION variable in gallery.php to check if the $_SESSION is set.
Although, I believe you will have to change the file name from gallery.html to gallery.php
<?php
if (!isset($_SESSION['secret_variable'])
{
echo "<br/>Error Message<br/>";
return;
}
?>
Continue with the rest of the code. If the user access the gallery.php by specifying the URL, he/she will end up with Error Message.
The $_SESSION['secret_variable'] should be set after you figure out that the user has a valid username and password to ensure a valid login.
Thanks.. :)
You need to set your login status in sessions and check for the session in your to-be-secured pages.
<?php
session_start();
if (!isset($_SESSION['login_status'])) {
// Add permission denied message or redirect back to the login page
}
?>
However, this can be done in PHP pages, not in a page with .html extenstion (unless you have explicitly specified your web server configuration with an "AddType x-httpd-php .html" directive.)
Easiest way is using php. Save your gallery.html as gallery.php or enter below code on top of the gallery.html page before all the coding. Then use a SESSION variable ($_SESSION['userID'] in here) to store current login details.
<?php
if(! isset($_SESSION['userID'])){ //userID or something to identify the user
header('Location:login.php'); //redirects to the login page
}else{
header('Location:gallery.php'); //redirect to the gallery.php for valid login
}
?>
There is no way of preventing someone from typing in the URL and requesting the page. THe only thing you'll be able to do is check if they are logged in on the page itself.
You have to set the cookie or session once the user is logging in. so you will set the session or cookie for the user. Every time while entering that particular url you have to check the session for showing that page or else redirect to the login page
I have a simple login form, username and password. Basically, When a user is anywhere on the website, he can click a link that will take him to the login page. After login, he is redirected to the page he came from initially.
The problem:
let's say I was in the "/posts" page, and I clicked to login, so now I am on "/users/login".
- if the login is correct, or the login is incorrect and nothing is filled in the username textbox, everything works as expected (if it's correct I am redirected back to "/posts" otherwise I receive the "wrong username or password" message, I try to login again correctly and then I am redirected to "/posts";
if the login is incorrect, and some text is filled in the username textbox, after the login I receive the "wrong username or password" message, which is good, but if I fill in the form again, no matter wheather it is correct or not, I get "You are not authorized to access that location." If I try to log for the third time, the login works, but I am redirected to "/users/posts" instead of "/posts" (the value for the redirect page, which is stored in a session, is still "/posts" ).
This is the code:
function beforeFilter () {
parent::beforeFilter();
$this->Auth->allowedActions = array( 'confirmation');
$this->Auth->fields = array(
'username' => 'usr_username',
'password' => 'usr_password'
);
$this->Auth->userScope = array('User.usr_confirmed' => 1);
if($this->action == 'signup') {
$this->Auth->authenticate = $this->User;
}
}
function login () {
if ( $this->Auth->user() ) {
$this->redirect($this->Session->read('page'));
exit();
}
}
function logout () {
$this->Session->destroy('username');
$this->redirect('/');
exit();
}
it sounds like your form action is redirecting to a restricted area. check the form action attribute.
Put this at the bottom of app/views/layouts/default.ctp to help debug the session:
<?php debug($session->read()); ?>
The Auth.User key will be filled with data when you are logged in, but, more importantly, the Auth.redirect key will containing the URL of the last restricted page visited, this is where AuthComponent plans on redirecting to once you log in.
Are you storing a restricted page's URL in the your session's page key?
If so, AuthComponent can provide that functionality already with its Auth.redirect key. All you need to do is link to the restricted page instead of the login page and AuthComponent will populate that key automatically and handle the redirect after login.
echo $html->link('Login', array('controller' => 'users', 'action' => 'profile'));
If not, then why not consider populating that key instead. Since AuthComponent already checks for and acts on this key, you might gain some free functionality.
In any event, here is what a custom login method should look like in your case, but if any of the advice above will work then you can simply leave out the login method all together and use the default functionality:
function login () {
// log the user in
if ($this->Auth->login()) {
// your session redirect
if ($this->Session->read('page')) {
$this->redirect($this->Session->read('page'));
}
// auth's session redirect
if ($this->Session->read('Auth.redirect')) {
$this->redirect($this->Session->read('Auth.redirect'));
}
// default redirect
$this->redirect($this->Auth->loginRedirect);
}
}