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

Posted

技术标签:

【中文标题】在 playframework 中拦截请求并检查授权【英文标题】:Intercept request and check authorization in playframework 【发布时间】:2015-08-05 19:29:55 【问题描述】:

我在 Java 中使用play framework 2.4.2,我想通过拦截所有请求并检查是否设置了会话值来验证用户是否已登录。所以我扩展了DefaultHttpRequestHandler并覆盖了createAction方法来拦截所有请求。但是,我还没有找到验证会话的好方法。

选项 1 - 失败

当我尝试获取会话值时,我得到一个运行时异常:There is no HTTP Context available from here

下面是我正在使用的课程:

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 - 太容易忘记注释

我注意到一些网站记录了一种不同的方法,而是创建一个action composition 并将适当的注释添加到每个控制器类或方法中。

这种方法的问题是它需要开发人员记住添加注释。我宁愿将其反转以默认阻止每条路由,然后为不需要验证的路由添加注释。

几个记录动作组合的网站:

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

问题

有没有办法全局验证用户是否应该有权访问页面以及如何获取会话变量?

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

【问题讨论】:

您还可以注释控制器,因此您可以使用动作组合来创建注释,您可以在其中检查用户,无论您需要什么,然后只需对所有控制器进行一次注释。但除此之外,Action Composition 绝对是通常的方式。 【参考方案1】:

即使我会重新考虑使用动作组合,您也可以修复选项 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"));
                
            
        ;
    

这样,除非明确注释,否则每条路由都需要验证。

从代码中可以看出,会话可以通过 Context 获得。

【讨论】:

谢谢,这正是我想要的!关键是返回new Action.Simple(),所以...简单!

以上是关于在 playframework 中拦截请求并检查授权的主要内容,如果未能解决你的问题,请参考以下文章

在 playframework 中重新加载自定义文件更改的应用程序

PlayFramework 之类的中间件

Eclipse设置断点无效无法拦截请求进行Debug调试

移动端自动化之请求拦截

MySQL逻辑架构图

如何在 playframework 中自动修剪请求参数