Ограничение доступа к методу в Play Framework с авторизацией — Java

У меня проблемы с пониманием идеи авторизации в 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 и переопределив методы getUserName и onUnauthorized следующим образом:

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 в моем сценарии?


person Seeker    schedule 21.02.2017    source источник
comment
Только для тех, кто хочет знать, как реализовать Security.Authenticated. я нашел следующую хорошую статью, которая может быть хорошей помощью: alexgaribay.com/2014/06/16/   -  person Seeker    schedule 23.02.2017


Ответы (1)


Вы смешиваете авторизацию и аутентификацию.

Вот хорошая тема: Аутентификация против авторизации

Мне нравится этот ответ:

Аутентификация = логин + пароль (кто вы)

Авторизация = разрешения (что вам разрешено делать)

Аутентификация == Авторизация (за исключением анонимных пользователей), если вы разрешаете делать что-либо для всех пользователей, которых вы знаете (т. е. Прошедших проверку пользователей)

Основной целью Deadbolt является авторизация (уже авторизованные пользователи ). Ваша главная цель — Аутентификация.

Я бы посоветовал вам использовать Pac4J, это библиотека Аутентификации не только для Play, и у него есть версии как для Java, так и для Scala. Есть хороший пример проекта: https://github.com/pac4j/play-pac4j-java-demo

Я сам использую эту библиотеку в своих проектах и ​​задача

В будущем я буду добавлять больше вызовов методов в этот REST API. Так что я буду повторно использовать ту же авторизацию и для этих будущих API REST.

Я решаю так же просто, как просто добавить конфигурацию в 'application.conf`:

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

Только не забудьте добавить Security filter. Эта функция присутствует в примере проекта, так что просто скопируйте и попробуйте.

Другой пример формы официальной страницы:

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"
  }}
]
person Andriy Kuba    schedule 21.02.2017
comment
Спасибо за разъяснения по поводу аутентификации и авторизации. я рассмотрю модуль pac4j. - person Seeker; 22.02.2017