Java 在playframework中拦截请求并检查授权

Java 在playframework中拦截请求并检查授权,java,playframework,authorization,playframework-2.4,Java,Playframework,Authorization,Playframework 2.4,我在Java中使用PlayFramework2.4.2,我想通过拦截所有请求并检查会话值是否设置来验证用户是否登录。因此,我扩展并重写了createAction方法来拦截所有请求。但是,我还没有找到验证会话的好方法 选项1-失败 当我尝试获取会话值时,我得到一个运行时异常:这里没有可用的HTTP上下文 下面是我正在学习的课程: public class RequestHandler extends DefaultHttpRequestHandler { @Override pub

我在Java中使用
PlayFramework2.4.2
,我想通过拦截所有请求并检查会话值是否设置来验证用户是否登录。因此,我扩展并重写了
createAction
方法来拦截所有请求。但是,我还没有找到验证会话的好方法

选项1-失败 当我尝试获取会话值时,我得到一个运行时异常:
这里没有可用的HTTP上下文

下面是我正在学习的课程:

public class RequestHandler extends DefaultHttpRequestHandler {
    @Override
    public Action createAction(Http.Request request, Method method) {
        session("loggedIn"); // Throws runtime Exception: no HTTP Context
    }
}
选项2-丑陋 由于会话在技术上是一个cookie,我可以使用如下代码从标头中检索值:

for(String cookie : request.headers().get("Cookie")){
    System.out.println("cookie: "+cookie);
}
但是我必须解析cookie字符串,它看起来像下面的一行,以获得loggedIn值。为了我的口味,我把它弄脏了

_ga=GA1.1.1508004144.1421266376; ki_r=; ki_t=1438789543788%378129908%3B1438789543788%3B1%3B1; PLAY_SESSION=0570411c3eb55ad230681539ddcfaa4220583fd-loggedIn=1
选项3-太容易忘记注释 我注意到一些网站记录了不同的方法,而是创建了一个
并为每个控制器类或方法添加适当的注释

这种方法的问题是需要开发人员记住添加注释。我更愿意逆转这一点,在默认情况下阻止每个路由,然后向不需要验证的路由添加注释

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface NoAuthRequired {}
记录动作组合的两个站点:

  • 问题: 是否有方法全局验证用户是否应该访问某个页面,以及如何访问会话变量?


    *请注意,我对使用第三方插件进行身份验证不感兴趣。

    即使我会重新考虑使用动作合成,您也可以修复选项1

    创建自定义注释以标记不需要验证的操作

    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NoAuthRequired {}
    
    然后更改HttpRequestHandler实现

    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"));
                    }
                }
            };
        }
    }
    
    公共类RequestHandler扩展了DefaultHttpRequestHandler{
    @凌驾
    公共操作createAction(Http.Request请求,方法actionMethod){
    返回新的Action.Simple(){
    @凌驾
    public F.Promise调用(Http.Context ctx)抛出可丢弃的{
    //如果操作带有@NoAuthRequired注释,或者用户已登录,请委托给它
    if(actionMethod.isAnnotationPresent(NoAuthRequired.class)| | ctx.session().containsKey(“loggedIn”)){
    返回委托呼叫(ctx);
    }
    //否则,将阻止访问
    否则{
    返回F.Promise.pure(禁止(“不允许”);
    }
    }
    };
    }
    }
    
    这样,除非显式注释,否则每个路由都需要验证


    正如您从代码中看到的,会话可以通过上下文进行使用。

    您还可以对控制器进行注释,因此您可以使用动作合成创建一个注释,在该注释中,您可以检查用户是否有任何需要,然后只需对所有控制器进行一次注释。但是除了动作组合之外,这绝对是我通常的方式。谢谢,这正是我想要的!键正在返回新的Action.Simple(),因此。。。简单!