使用授权限制对 Play Framework 中方法的访问 - Java

Restricting Access to method in Play Framework with Authorization - Java

我无法理解 PlayFramework(2.5 版)中的授权概念。我的情况是我有一个 REST API 方法 getUser,我想通过使用自定义请求 header 中名为 "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 中有 authorization 可用,但我无法理解。我试图通过扩展 class 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());
    }
}

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

另外我知道有一个名为Deadbolt which is used for authorization but I read its documents and I am not able to integrate it. It was relatively complex integration for a beginner like me. I was confused about how to use it. I thought about using SubjectPresent controller authorization 的模块,但我仍然无法成功实现它。

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

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

这是一个很好的线程:Authentication versus Authorization

我喜欢这个答案:

Authentication = login + password (who you are)

Authorization = permissions (what you are allowed to do)

Authentication == Authorization(不包括匿名用户)如果您允许为您认识的所有用户做某事(即 已验证 用户)

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

我建议你使用Pac4J, it Authentication library not only for Play, and it has versions as for Java as for Scala. There is a good sample project: https://github.com/pac4j/play-pac4j-java-demo

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

As in future i will be adding more method calls to this REST api. So i will be reusing the same authorization to those future REST apis as well.

我解决起来很简单,只需在'application.conf`中添加配置即可:

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

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

另一种形式 the official page:

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"
  }}
]