Spring Security redirect back to refer URL after login and logout - spring

I am using Spring Security for authentication. The login and logout buttons are placed on the page layout, which is used by all pages. I have a BookController which needs a parameter for the create action (e.g., an image id):
class BookController {
#Secured("ROLE_USER")
def create() {
def someImage = params.imageId
...
}
#Secured("ROLE_USER")
def show() {
...
}
...
}
My LoginController is:
class LoginController {
...
def auth() {
...
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
}
...
}
This will redirect the user to the base URL after login was successful. I want to have the user always be redirected to the refer URL, which is the URL before he was successfully logged in.
For example:
The user is not logged in. He is at home/index and want to access book/create, which is only available for logged-in users. In this case, Spring Security will redirect the user to login/auth and (after he is successfully logged in) to / (which is the base URL).
I want to have the redirect go to the URL the user has been trying to access, which in this case is book/create. This should also be the case for any other action. If a not-logged-in user on home/index tries to access book/show/32333, he will be redirected to login/auth, and, after he successfully logs in, back to book/show/32333.
How can I implement that?

I had the following solution:
HttpSession session = request.getSession(false)
def referUrl
def referParamsMap
def referParams = "?"
if(session != null) {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response)
if(savedRequest != null) {
referUrl = savedRequest.getRedirectUrl()
referParamsMap = savedRequest.getParameterMap()
referParamsMap.each { referParams += "${it.key}=${it.value[0]}&" }
}
}
println "referUrl "+referUrl+referParams
if(referUrl != null)
redirect url: referUrl+referParams
else
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
The only problem is, that if a not logged in user is on a page and loggs in (by clicking on a login link at the layout GSP) he will alway be redirected to the defaultTargetUrl not to the page he has been before.
Is there a way to get the correct url in this case?

Related

On Google login redirect to https://myaccount.google.com/ when multiple Google account is logged in at the same time in browser - Laravel

I am tired with Google login, when single Gmail account logged in browser everything fine, but when two or more Gmail account logged in browser then login successfully but redirect in the google account setting (url:https://myaccount.google.com), here is my controller code. I want to redirect to back page.
public function redirect()
{
return Socialite::driver('google')->redirect();
}
public function callback()
{
$googleUser = Socialite::driver('google')->user();
$existUser = User::where('email',$googleUser->email)->first();
if($existUser) {
Auth::loginUsingId($existUser->id);
}
else {
$user = new User;
$user->first_name = $googleUser->name;
$user->email = $googleUser->email;
$user->google_id = $googleUser->id;
$user->password = bcrypt(rand(1,10));
$user->save();
Auth::loginUsingId($user->id);
}
return back();
}
Redirect to this page, I want to redirect back page
This happens because of return back(); since your server is redirecting back to Google through the HTTP Referer header. This header is unreliable, please do not use it.
Instead, before login with google, save the current URL in the user session and after the login callback, redirect to that URL. In this way, you will be able to bring the user back to the original page.

controllers in web frameworks ? [ruby, Grails, etc..] How do they work?

So the thing that I want to do is direct the login page to the admin page(e.g: "admin.gsp") if username "admin" is entered and password "pass" is entered. or direct it to the user page if username "user" and password "pass" is entered
However I do not understand how exactly controller works.
So when you redirect the page to a specific controller and specific method, how do you make it redirect it to a specific page. What code do you implement inside that method ?
to explain my question better. Below we have the code for controller User, with an if else statement depending on what the user typed in the login boxes.
package file_download
class UserController {
def index() {
//code that directs the page to username page, let's call it or user.gsp
}
def login = {
if(params.username == "admin" && params.password == "pass")
{
session.user = "admin"
redirect(controller:"admin",action:"admin")
}
else if(params.username == "user" && params.password == "pass")
{
session.user="user"
redirect(controller:"user",action:"index")
}
else
{
flash.message = "login failed"
}
redirect(controller:"user",action:"login")
}
def logout = {
session.user = null
redirect(action: 'index')
}
}
now here, we have the admin controller, with the action index, that should have a code implemented to direct the page to... admin.gsp, or admin.html, watever the admin page is called
package file_download
class AdminController {
def index() {
//code that takes us to admin page let's call it admin.gsp
}
}
How do we exactly do that ?
I need a little bit of an explanation on controllers.
Thank you. Please ask if you need more clarification on the question as I will edit it.
I think you are having wrong assumptions. In Grails (I don't know rails) when you go to the login page, let's say
/app/user/login
then, at FIRST the controller method is being called (def login()), so your logic shouldn't go there, it should actually do nothing and by convention it will end up rendering login.gsp. Next, your user fills in his username/pass and submits form, there goes the second request let's say to
/app/user/auhtenticate
and here's where your logic should go and the redirects will work as you expect
So basically - controller method is called first and (unless you specify gsp to be rendered or do a redirect) after the method is executed, the gsp view is being rendered
I know nothing of rails, however in grails what you are looking for is render.
Render:( http://grails.github.io/grails-doc/latest/ref/Controllers/render.html )
so the code would look something like this
def index() {
render view: "/directory/inside/views/admin" model: [thing1: "Thing One"]
}

How to redirect to the method of a controller after user doing authentication on codeigniter?

I am using the Default Controller to make the user authentication. What I am trying to do is whatever is the page the user request news/add or news/index or themes/all or maps/view, if he is not logged in, he or she will be directed to the log in page and then redirected to the page he wanted to go, not always the same page.
You can your the
CodeIgniter User Agent Library and Session Library to store and use the referring url. The user agent library is basicly accessing the $_SERVER['HTTP_REFERER'] value.
NOTE: from the php.net website:
Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.
so this is not a foolproof method.
if ($this->agent->is_referral()) {
$this->session->set_userdata('prev_url', $this->agent->referrer());
}
// later, when login is successful
$prev_url = $this->session->userdata('prev_url');
if( $prev_url ) {
redirect($prev_url);
}
one way is to do it in the constructor of your controller. that way they are redirected before going to the news/add etc.
so for example you create a model called "sentry" and a "getUser()" method to check the browser cookie to see if the user is authorized. if they are not authorized have it return false. if they are authorized have it return $user so then you have it available for your other methods.
function __construct() {
parent::__construct();
$this->load->model( 'sentry' );
if ( ! $this->user = $this->sentry->_getUser() )
{ redirect( '/login/', 'refresh' ); }
}
so then for example you could have $this->user->name etc etc available to any method in the controller. And $this->user will also automatically be available in all the view files of this controller.
I do this by extending my controller and I check in constructor if person is logged in or not, if person is logged in I save to the session current URL, and redirect person to the login page (if same constructor is applied (controller one) I make exception to not save current URL to the session) after logging in I call redirect function to the session variable.
How to extend your controller is done here http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-Base-Classes-Keeping-it-DRY
note that when your controller is extended you use $this->data['variable_sent_to_view'] and you can omit second parameter of $this->load->view()
here is some example code assuming you know how your login controller works
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
function __construct() {
parent::__construct();
$this->output->enable_profiler(FALSE);
if ($refer = $this->session->flashdata('refer')) {
$this->data['refer_page'] = $refer; // $this->data['refer_page'] is variable that you are interested in
unset($refer);
} else {
$this->data['refer_page'] = base_url(); //default refer_page
}
//check if user is NOT logged in
if (!$logged_in) {
$this->_setRefer(); //this is private function
}
// else dont care about it
}
private function _setRefer() {
$invalid_method = array('search', 'login'); // if method is 'search' or 'login' url will not save in session (it will stay same as was before)
$valid_refer = TRUE;
if (in_array($this->router->method, $invalid_method)) {
$valid_refer = FALSE;
}
if (!(count($_POST) > 0) && $valid_refer === TRUE && !$this->input->is_ajax_request()) {
$this->session->set_flashdata('refer', current_url());
} else {
$this->session->set_flashdata('refer', $this->data['refer_page']);
}
}
}
now in after succesful login redirect to $this->data['refer_page'], but note that login controller must by extended by MY_Controller.
this script also takes care about what happens if user made mistake and inserted wrong password (page will reload but "old" url stays)

CakePHP 2 AJAX redirections

I'm using AJAX in my web-app stuffs like search but if the user has been logged out, the ajax function return nothing because the redirection (from the action 'search' to the action 'login') has not been handled correctly.
Is it possible to redeclare the method 'redirect' in AppController to render the right action when a redirect hapend in an AJAX call ?
Thank you,
Sébastien
I think your best bet would be to setup you ajax to call to respond correctly to an invalid response. As it seems to be an important part of your app I would pass a 'loggedin' variable with every ajax request, so the client can tell as soon as the user has been logged out.
Update
In the case you want to keep a user logged in, you simply have to put the logged in/cookie check in something like your AppController::beforeFilter() that gets run with every request. for example:
public function beforeFilter() {
if($this->Auth->user() {
// USer is logged in, it's all gravy
} else {
// User is not logged in, try to log them in
$userData = $this->Cookie->read('User');
if(!empty($userData)) {
// Function that grabs info from cookie and logs in user
}
}
}
This way there will be no redirect as the user will be logged in as long as they have a cookie.
Another approach would be to allow everyone access to the Ajax function:
public function beforeFilter() {
$this->Auth->allow(array('my_ajax_method'));
}
And then check the user is authenticated in the method itself:
public function my_ajax_method() {
if (!$this->Auth->user()) {
//user not authenticated
$result = "requires auth";
}
else {
// use is authenticated
// do stuff
$result = 'result of stuff';
}
$this->set(compact('result'));
}
You will need to check the result of the ajax call in your javascript and act accordingly.

Redirect in onSubmit() method of simpleformcontroller

I am new to spring framwork and using 2.5 version.
My requirement is that based on some value of command object in submit method I have to redirect the user to url /out.This is not defined as any view.But used for logout.
Ex.http://127.34.22.22:8080/abc is the invoking url and the url after redirect needed is the http://127.34.22.22:8080/out.
I tried redirect it is working only when I hardcode the whole url,but unable to redirect at runtime.
if(attribute is true){
return new ModelAndView("http://127.34.22.22:8080/out");
}else{
return new ModelAndView(getSuccessView());
}
Above code is working but I don't want to hardcode whole url.
Thanks in advance.
ModelAndView expect an VIEW name but not an URL. (ModelAndView(String viewName))
What you need is to pass an an RedirectView as parameter to ModelAndView(View view)
Example:
if(attribute) {
return new ModelAndView(new RedirectView("http://127.34.22.22:8080/out");
} else {
...
}

Resources