2

我无法理解 PlayFramework(2.5 版)中的授权概念。我的情况是我有一个 REST API 方法getUser,我想通过使用名为"X-Authorization". 现在我的控制器代码如下所示:

package controllers;

import models.User;
import org.bson.types.ObjectId;
import play.mvc.*;
import org.json.simple.*;
import views.html.*;

public class ApiController extends Controller {

    public Result getUser(String userId) {

        User user = User.findById(new ObjectId(userId));
        JSONObject userG = new JSONObject();

        //Some code to append data to userG before return
        return ok(userG.toJSONString());
    }
}

路由 URL 定义如下:

GET    /api/user/:id    controllers.ApiController.getUser(id)

选项 1可能是检查方法内的授权令牌并检查其他凭据,但我想在它获取调用方法getUser之前限制访问。getUser将来我会向这个 REST API 添加更多的方法调用。因此,我也将对未来的 REST API 重用相同的授权。

我发现 Play Framework 中有可用的授权,但我无法理解。我尝试通过扩展类Security.Authenticator和覆盖方法来实现授权getUserNameonUnauthorized如下所示:

package controllers;

import models.Site;
import models.User;
import org.json.simple.JSONObject;
import play.mvc.Http.Context;
import play.mvc.Result;
import play.mvc.Security;

public class Secured extends Security.Authenticator {
    @Override
    public String getUsername(Context ctx) {
        String auth_key = ctx.request().getHeader("X-Authorization");
        Site site = Site.fineByAccessKey(auth_key);

        if (site != null && auth_key.equals(site.access_key)) {
            return auth_key;
        } else {
            return null;
        }
    }

    @Override
    public Result onUnauthorized(Context ctx) {

        JSONObject errorAuth = new JSONObject();
        errorAuth.put("status", "error");
        errorAuth.put("msg", "You are not authorized to access the API");

        return unauthorized(errorAuth.toJSONString());
    }
}

然后我将注释附加到getUser带有@Security.Authenticated(Secured.class). 它工作正常并返回未经授权的错误。但现在我不确定这是否是首选方式。我觉得这不是正确的方法,因为函数覆盖的名称也getUsername表明了这一点。我没有检查会话或 cookie 中的任何用户名,而只是检查请求标头中存在的令牌。

另外我知道有一个名为的模块Deadbolt用于授权,但我阅读了它的文档并且我无法集成它。对于像我这样的初学者来说,这是相对复杂的集成。我对如何使用它感到困惑。我考虑过使用SubjectPresent控制器授权,但我仍然无法成功实施。

最后你们建议我应该使用Security.Authenticator我实施的方式吗?或者你是否建议我去我的第一个选项是检查getUser方法内部的授权?或者任何人都可以告诉我如何Deadbolt在我的场景中实现?

4

1 回答 1

5

您正在混合授权和身份验证。

这是一个很好的线程: 身份验证与授权

我喜欢这个答案:

身份验证= 登录名 + 密码(你是谁)

授权=权限(你可以做什么)

身份验证==授权(不包括匿名用户),如果您允许为您认识的所有用户(即经过身份验证的用户)做某事

Deadbolt的主要目标是授权(已经通过身份验证的用户)。您的主要目标是Authentication

我建议您使用Pac4J,它不仅用于 Play 的身份验证库,而且它具有 Java 和 Scala 的版本。有一个很好的示例项目:https ://github.com/pac4j/play-pac4j-java-demo

我自己在我的项目和任务中使用这个库

将来我会向这个 REST api 添加更多的方法调用。所以我也将对那些未来的 REST api 重用相同的授权。

我只需在“application.conf”中添加配置即可轻松解决:

pac4j.security {
  rules = [
    {"/admin/.*" = {
      authorizers = "ADMIN"
      clients = "FormClient"
    }}
  ]
}

只是不要忘记添加安全过滤器。此功能存在于示例项目中,因此只需克隆并尝试。

官方页面的另一个示例:

pac4j.security.rules = [
  # Admin pages need a special authorizer and do not support login via Twitter.
  {"/admin/.*" = {
    authorizers = "admin"
    clients = "FormClient"
  }}
  # Rules for the REST services. These don't specify a client and will return 401
  # when not authenticated.
  {"/restservices/.*" = {
    authorizers = "_authenticated_"
  }}
  # The login page needs to be publicly accessible.
  {"/login.html" = {
    authorizers = "_anonymous_"
  }}
  # 'Catch all' rule to make sure the whole application stays secure.
  {".*" = {
    authorizers = "_authenticated_"
    clients = "FormClient,TwitterClient"
  }}
]
于 2017-02-21T21:40:33.537 回答