[SOLVED] Active Session Check

I have a page that has ajax elements. If a user cicks an ajax link but his session has timed out, Yii returns the fully rendered loginUrl.

Instead, I’d like to customize this behavior and have a timed out session throw a 401 http exception and have jQuery handle the error with a redirect (and maybe display a nice ‘you have timed out’ message.

I don’t see where Yii actually performs the check. It appears to happen even before ‘beforeAction’ is parsed.

So I have my code that throws an exception in ‘beforeAction’ but it is never reached since Yii is redirecting before I can handle it myself.

Where does this happen?

Thanks!

I had a similar situation come up some time ago, and these were my notes on resolving it:

The redirect is in the CWebUser loginRequired method.

http://danaluther.blogspot.com/2010/04/loginrequired-and-ajax-updates.html

You might come up with a more elegant solution. I ended up altering the CWebUser

Thanks Dana, I’ll take a look :)

I created WebUser.php in protected/components, then modified the config/main.php ‘user’ component to use the WebUser class.

Here is WebUser:




<?php


class WebUser extends CWebUser

{

    public function loginRequired()

    {

       $app = Yii::app();

       $request = $app->getRequest();

       

       $this->setReturnUrl( $request->getUrl() );

       

       if ( ($url = $this->loginUrl) !== null )

       {

           if (is_array($url))

           { 

				 $route=isset($url[0]) ? $url[0] : $app->defaultController;

				 $url=$app->createUrl($route,array_splice($url,1));

           }

           

           if ( $request->isAjaxRequest )

           {

				 //$this->renderPartial('application.views.main.sessionTimeout', array(), false, true);

				 echo "This output is never given to the client...";

           } 

           else

           {

				 $request->redirect($url);

           }

       }

    }

}



That should be what you have for the class as well, however Yii completely ignores this logic and the app continues to display a fully rendered login screen inside the update div.

Any idea why?

I think it must be failing the first if check:


if ( ($url = $this->loginUrl) !== null ){...}

and falling through to the throw new CHttpException

I didn’t have one set for my application, I left it default so never caught that.

Try reordering it like so:




class WebUser extends CWebUser

{

    public function loginRequired()

    {

       $app = Yii::app();

       $request = $app->getRequest();

       

       $this->setReturnUrl( $request->getUrl() );

       

       if ( $request->isAjaxRequest )

       {

          //$this->renderPartial('application.views.main.sessionTimeout', array(), false, true);

          echo "This output is never given to the client...";

       } else {


          if ( ($url = $this->loginUrl) !== null )

          {

              if (is_array($url))

              { 

                  $route=isset($url[0]) ? $url[0] : $app->defaultController;

                  $url=$app->createUrl($route,array_splice($url,1));

              }

               $request->redirect($url);


          }

          else 

            throw new CHttpException(403, Yii::t('yii', 'Login Required'));

       }

    }

}



Still no go.

I commented out the non-ajax redirect to see if the request would just die but somehow the app still managed to redirect itself to the login page and render into my update div. That’s true even if I use CWebUser. To say it another way…WTF?

All caches are cleared and disabled so I’m at a loss.

Makes me think something’s broken in latest.

Well, you could verify that it’s actually running the method by adding in some Yii log statements or just straight up ending the app when it comes to that point. Depends on your frustration level ;)

(Note: make sure you have logging info enabled in the config)

If you want to add some log statements, just at the very beginning of the loginRequired method, add:




Yii::log('Checking Login Required', 'info', 'webuser.loginrequired');



If you’re beyond that frustration level, at the top of the loginRequired function pop in:




   echo "What the WHAT?!?";

   Yii::app()->end();



Either way, you’ll know you’re getting to the right place. Do NOT advise trying option 2 on anything other than a local testing environment ;)

Another thought I had, was that you could do a redirect to your session timed out partial –

Where you have:




//$this->renderPartial('application.views.main.sessionTimeout', array(), false, true);



instead do something like:




  $request->redirect('/site/sessionTimeOut');



and just have an action in the site controller that will pull up the partial you linked above. This way, it’ll still do the inset shenanigans it’s doing now, but instead of drawing the whole site in, you should get just the partial view in your update div.

’ loginRequired()’ was never getting called so I started looking at why that might be the case.

I extend from a BaseController to do some credentials and date range checking and in there I had code that redirected to the login page if the user was ‘guest’.

Instead of redirecting in that way, I now call Yii::app()->user->loginRequired when the user is guest and that solved the issue.

Duh. I caused my own unnecessary drama.

Your override works perfectly, Dana. Thank you very much for the help, it’s greatly appreciated =D

Hello drech,

I’ve had the exact problem, and I solved it like that :

instead of $user->loginRequired() I wrote

$url = CHtml::normalizeUrl(array("Site/login"));

echo “<script type=‘text/javascript’>window.location= ‘$url’;</script>”;

So now it stopped rendering the login in update div, but redirect the whole window to the login page

I know you solved it, but I liked to share my idea too :)

the best solution is this




$(document).ready(

    function() {

        $("body").ajaxError(

            function(e,request) {

                if (request.status == 400) {

                    //window.location.reload();

                    //window.location.href = "/myapp/login";

                    // handle it as you wish

                }

            }

        );

    }

);



or




$.ajax({

			type: 'POST',

			url: '',

			beforeSend: function() {

				},

			complete: function() {

				showMessage.close();

			},

			error: function(jqXHR, textStatus, errorThrown) {

				if (jqXHR.status == 400)

                                   // handle login here you could have your app send a custom error status code


			,

			success: function(msg){

			}

		});




i am new in Yii … any on knows ? where yii-user-management stores login session ? any idea ??

or what it do for authenticaion ?