Intercept request and check authorization in playframework

此生再无相见时 提交于 2019-12-04 15:07:08

问题


I'm using play framework 2.4.2 with Java and I want to validate that a user is logged in by intercepting all requests and checking if a session value is set. So I have extended the DefaultHttpRequestHandler and overridden the createAction Method to intercept all requests. However, I have not found a good way to validate the session.

Option 1 - Fail

When I try to fetch the session value I get a runtime exception: There is no HTTP Context available from here

Below is the class I'm working with:

public class RequestHandler extends DefaultHttpRequestHandler {
    @Override
    public Action createAction(Http.Request request, Method method) {
        session("loggedIn"); // Throws runtime Exception: no HTTP Context
    }
}

Option 2 - Ugly

Since the session is technically a cookie I can retrieve the value from the header with code like the following:

for(String cookie : request.headers().get("Cookie")){
    System.out.println("cookie: "+cookie);
}

But then I have to parse the cookie string which looks like the following line to get the loggedIn value. To dirty for my taste.

_ga=GA1.1.1508004144.1421266376; ki_r=; ki_t=1438789543788%378129908%3B1438789543788%3B1%3B1; PLAY_SESSION=0570411c3eb55ad230681539ddcfaa4220583fd-loggedIn=1

Option 3 - Too easy to forget the annotation

I notice some websites document a different approach and instead create an
action composition and add the appropriate annotation to every controller class or method.

The problem with this approach is it requires the developer to remember to add the annotation. I would prefer to reverse this to block every route by default and then add an annotation to the routes that do not need the validation.

A couple sites that document action composition:

  1. http://alexgaribay.com/2014/06/16/authentication-in-play-framework-using-java/
  2. https://www.playframework.com/documentation/2.2.1/JavaGuide4

Question

Is there a way to globally validate if a user should have access to a page and how do I get at the session variable?

*Please note that I'm not interested in using a third party plugin for authentication.


回答1:


Even if I would re-consider using action composition, you can fix Option 1.

Create a custom annotation to mark the actions that don't need validation.

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface NoAuthRequired {}

Then change your HttpRequestHandler implementation.

public class RequestHandler extends DefaultHttpRequestHandler {
    @Override
    public Action createAction(Http.Request request, Method actionMethod) {
        return new Action.Simple() {
            @Override
            public F.Promise<Result> call(Http.Context ctx) throws Throwable {
                // if the action is annotated with @NoAuthRequired or user is logged in delegate to it
                if (actionMethod.isAnnotationPresent(NoAuthRequired.class) || ctx.session().containsKey("loggedIn")) {
                    return delegate.call(ctx);
                }
                // otherwise, block access
                else {
                    return F.Promise.pure(forbidden("You're not allowed"));
                }
            }
        };
    }
}

In this way, every route requires validation unless explicitly annotated.

As you can see from the code, the session is available through the Context.



来源:https://stackoverflow.com/questions/31841240/intercept-request-and-check-authorization-in-playframework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!