Session Expire Symfony 2 Ajax - ajax

My application uses ajax to request data. I'm using Symfony2, and when the session expires and I make a request with ajax, the login form is shown inside the main area on my application, and not as another view as should be. How can solve this problem. Thanks

I would suggest creating event listener which will be listening for every request:
services.yml:
your_request_listener:
class: Acme\AppBundle\EventListener\RequestListener
arguments: [#security.token_storage]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onRequest }
In this event listener I would check for type of request so this would be only Ajax request listener. When request is ajax type then I would check if session has expired - if so, I would create response which will be valid response for ajax request (i.e. JsonResponse) and set this response to be sent to user.
class RequestListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->isXmlHttpRequest()) {
return; //we dismiss requests other than ajax
}
//now you check if user is authenticated/session expired/whatever you need
$token = $this->tokenStorage->getToken();
if ($token === null) {
//now you create response which you would expect in your js doing ajax, for example JsonResponse
$response = new JsonResponse(); //you should give some content here
$event->setResponse($response); //now you override response which will be sent to user
}
}
}

You could use an entry point in which you verify if the request is an AJAX request. If yes, you return a JSON response with 401 HTTP status code. Then in JS code you verify the HTTP status code. If 401, then redirect to login page.
You can read my post here with the complete solution (see my own answer to my own question). This solution is based on this excellent post.

Related

Vue API Calls and Laravel Middleware

Is it possible to globally set a listener on API calls made with Axios in Vue? The Laravel back-end has middleware set up on each endpoint that will either give the requested data or return a message saying that they need to check their messages. My goal is to capture that message and redirect the user to the page to view their message. I can't think of a way to do this other than setting something on each function that checks for the message and responds accordingly. There are hundreds of functions and that it wouldn't be a clean solution.
Any and all recommendations are welcome!
Using Axios Interceptors you can do something along these lines:
this.$http.interceptors.response.use(response => () {
// Redirect to a new page when you send
// custom header from the server
if (response.headers.hasOwnProperty('my-custom-header')) {
window.location.href = '/another-page';
}
// Or when you get a specific response status code
if (response.status === 402) {
window.location.href = '/another-page';
}
// Or when the response contains some specific data
if (response.data.someKey === 'redirect') {
window.location.href = '/another-page';
}
// ...or whatever you want
});

404 Error when Testing Request class validation through Chrome Postman Extension

Below is my Controller Action method. You can see I passed a param of Request Class to validate before going to save the data in database
public function store(RoleRequest $request)
{
}
My Request class is below.
class RoleRequest extends Request
{
private $Role;
public function __construct(IRole $_role) {
$this->Role = $_role;
}
public function authorize()
{
return true;
}
public function rules()
{
return [
'Role' => 'required|max:20|min:4,
];
}
}
Above code works perfectly when I run it through web page(blade).
I created one more controller for API to Send save request. Below is the code
class RoleApiController extends Controller
{
public function store(RoleRequest $request)
{
}
}
Issue comes, when I type just 1 char for role name and the Request class impose validation and I get 404 error This time I am sending request from Postman Extension in Chrome.
Error Details
The Validation Request class checks if your request is an ajax request or a normal request.
If it's a normal request it does: redirect()->back() with the validation messages in the session.
If it's an ajax request it shows a json object with the validation messages in it.
Frontend frameworks/libraries like for example jQuery add a header to an ajax request to let the backend know it's an ajax request. Laravel checks this header to decide what to do (using the isAjax or wantsJson methods).
Postman does not automatically send this header. So you should add one of the following headers manually:
Accept: application/json
X-Requested-With: XMLHttpRequest
Here is a screenshot of postman as an example:

Debugging Ajax requests in a Symfony environment

Not sure if SFDebug is any help in this situation. I am making an ajax post using jQuery. Which retrieves JSON data in my action URL and then makes a call to the Model method that executes the action. The part until my action URL, and the jQuery call to it work fine. With the data transmitted from the client to the server well received and no errors being made.
It is the part where it calls the method on the Model that is failing. My jQuery method looks like this:
$.post(url, jsonData, function(servermsg) { console.log(servermsg); }) ;
My server action is like this
public function executeMyAjaxRequest(sfWebRequest $request)
{
if($request->isXmlHttpRequest())
{
// process whatever
$servermsg = Doctrine_Core::getTable('table')->addDataToTable($dataArray);
return $this->renderText($servermsg);
}
return false;
}
The method of concern in the Table.class.php file looks like this:
public function addDataToTable($dataArray)
{
// process $dataArray and retrieve the necessary data
$data = new Data();
$data->field = $dataArray['field'];
.
.
.
$data->save();
return $data->id ;
}
The method fails up here in the model, when renderText in the action is returned and logged into the console, it returns the HTMl for SFDEBUG. Which indicates that it failed.
If this was not an Ajax call, I could debug it by seeing what the model method spat out, but this is a little tedious with Ajax in the mix.
Not looking for exact answers here, but more on how I can approach debugging ajax requests in a symfony environment, so if there are suggestions on how I can debug this, that would be great.
You must send cookie with session ide key via ajax
(Assuming you have XDEBUG configured on the server)
In order to trigger a debug session by an AJAX request you have to somehow make that request to send additional URL parameter XDEBUG_SESSION_START=1. For your example:
$.post(url + '?XDEBUG_SESSION_START=1', jsonData, function(servermsg) { console.log(servermsg); }) ;
You can also trigger it via cookie, but appending URL parameter usually easier.

XmlHttpRequest in Symfony2

Here follows my problem. In a Symfony2.1 controller I receive an Ajax call. If I use the Request object I'm not able to get the sent param. If I use the PHP _REQUEST object the param is found!
I can confirm that the request is XHR, if it matters.
Here is my code:
public function savedataAction(Request $request){
if($request->isXmlHttpRequest())
echo 'Ajax Call';
$param1 = $request->request->get('myParam'); // Nothing is returned, but $request is obviosly not null
$param2 = $_REQUEST['myParam']; // The value is given
....
}
Any idea?
PS: If helps, notice that the AJAX call is sent by the file uploader jQuery plugin provided by Valums.
Normally its:
// retrieve GET and POST variables respectively
$request->query->get('foo');
$request->request->get('bar', 'default value if bar does not exist');
Look here are the fundamentels.
http://symfony.com/doc/current/book/http_fundamentals.html
Edit:
$request in your case is only filled when you send the form from the Symfony2 site. It is possible, that the CSRF protection block the request.
Try this in your controller to get the Request object:
$request = $this->get('request');
http://symfony2forum.org/threads/5-Using-Symfony2-jQuery-and-Ajax

ASP.NET MVC ActionFilter - Determine if AJAX Request

I am using an ActionFilter to determine if a user has access to a specific resource such as an Account object (a la Rhino Security) before hitting an action. This is a global filter which redirects to an error page should the authorization value fail
I'm using the following code, which works fine for full page requests:
filterContext.Controller.TempData["ErrorMessage"] = string.Format("You are not authorized to perform operation: {0}", operation);
filterContext.Result = new RedirectResult("~/Error/AuthorizationError");
Ajax requests I do not want to apply a redirect, but rather return an error message. Is there a way to tell inside the action filter if this is an AJAX request or a regular full page (sorry not sure of the correct terminology) request?
Thanks in advance
JP
You could use the IsAjaxRequest extension method:
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
// it was an AJAX request
...
}
else
{
// it was a standard request
filterContext.Controller.TempData["ErrorMessage"] = string.Format("You are not authorized to perform operation: {0}", operation);
filterContext.Result = new RedirectResult("~/Error/AuthorizationError");
}

Resources