Pergunta

I am using play framework 2.1.5.. As this version of play does not support in built session timeout, I started implementing it functionally... Here is my code..

// Global.java file
@Override
public Action onRequest(Http.Request request, Method method) {
    System.out.println(" Request .... " + request.toString());
    return new Action.Simple() {
        public Result call(Http.Context ctx) throws Throwable {
            String lastActionTime = ctx.session().get("lastActionTime");
            if (lastActionTime != null && sessionExpired(Long.valueOf(lastActionTime))) {
                ctx.session().clear();
                flash("success", "Session expired");
                return redirect("/login");
            }
            return delegate.call(ctx);
        }
    };
}


private boolean sessionExpired(Long lastActionTime) {
    maxSessionTime = Integer.parseInt(Play.application().configuration().getString("maxSessionTime"));
    return ((System.currentTimeMillis() - lastActionTime) / MILLISECONDS_IN_A_MINUTE) >= maxSessionTime;
}

I am overriding the on request Method...
Session_ timed_ out contains logic where I fetch the session's last inactive time and subtract it from the current time to see if the difference has exceeded the maximum session time.

The problem now is that on session expire, a request fires to /login and it gives a html page as response.

The response is as follows..

<html xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <link rel="shortcut icon" href="/assets/img/favicon.png">
    <link rel="stylesheet" href="/assets/stylesheets/dashboard.css" type="text/css" media="screen" charset="utf-8">
</head>
<body>
<header class="clearfix">
    <h1>Login</h1>
</header>
<form action="/login" method="POST" >   
<div id=login_form>
    <h1>Sign in</h1>  
    <p class="success">
        Session expired
    </p>
    <p>
        <input type="email" name="email" placeholder="Email" value="">
    </p>
    <p>
        <input type="password" name="password" placeholder="Password" >
    </p>
    <p>
        <button type="submit">Login</button>
    </p>
</div>
</form>
</body>
</html>

The method that handles /login request is:

public Result login(){
        return ok(login.render(form(Login.class)));
}

My login class:

public static class Login{
        public String email;
        public String password;

        public String validate(){
            if (User.authenticate(email, password) == null){
                return "Invalid username or password";
            }
            return null;
        }
    }

How can I render this html page to the view?

A few observations...

  1. When a page request is captured by on request method, redirect to login is also considered as a page request and the page is rendered properly....

  2. When an ajax request is intercepted by on request redirect to login is also made as ajax call (X-Requested-With is present in header)....

Now how can I convert this ajax call to page request??

Foi útil?

Solução

You need two different strategies depending on the nature of the request. For AJAX requests, you could reply with some relevant http error code and implement some client-side code to redirect to your login page. For normal page requests, your current strategy will work fine.

Here's another way to achieve this.

Outras dicas

Remove the static keyword from your anonymous inner class:

public Result call (final Context ctx) {
    ...
}

Finally figured out the answer...

When an incoming request is a page request, redirect to login is also considered as a page request.. Hence the response is rendered on the screen...

But, when the incoming request is an ajax request, redirect to login is treated as an ajax request...

So, to render this response...

//Global.java

@Override
    public Action onRequest(Http.Request request, Method method) {
        System.out.println(request.path());
          return new Action.Simple() {
            public Result call(Http.Context ctx) throws Throwable {
                String lastActionTime = ctx.session().get("lastActionTime");
                if (lastActionTime != null && sessionExpired(Long.valueOf(lastActionTime))) {
                    ctx.session().clear();
                    flash("success", "Session expired");
                    return temporaryRedirect("/login");
                }
                return delegate.call(ctx);
            }
        };
    }

    private boolean sessionExpired(Long lastActionTime) {
        maxSessionTime = Integer.parseInt(Play.application().configuration().getString("maxSessionTime"));
        return ((System.currentTimeMillis() - lastActionTime) / MILLISECONDS_IN_A_MINUTE) >= maxSessionTime;
    }

In the client side,

$.ajaxSetup({
       error: function (XMLHttpRequest, textStatus, errorThrown) {
            document.open();
            document.write(XMLHttpRequest.responseText);
            document.close();
        }
    });

Thanks Avik & Mantithetical... But is there any other better way to achieve the same?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top