Базовая аутентификация в perl6 с Cro - PullRequest
0 голосов
/ 30 октября 2018

Я ищу простое решение для защиты моих маршрутов с помощью механизма базовой аутентификации с помощью Cro. В моем примере я хотел бы видеть 401 Unauthorized, если вы вообще не предоставляете учетные данные. Если вы предоставите неверные учетные данные, я хотел бы видеть 403 Forbidden

В моем примере кода я никогда не видел, чтобы вызывалось промежуточное ПО MyBasicAuth:

class MyUser does Cro::HTTP::Auth {
    has $.username;
}

subset LoggedInUser of MyUser where { .username.defined }

class MyBasicAuth does Cro::HTTP::Auth::Basic[MyUser, "username"] {
    method authenticate(Str $user, Str $pass --> Bool) {
        # No, don't actually do this!
        say "authentication called";
        my $success = $user eq 'admin' && $pass eq 'secret';
        forbidden without $success;
        return $success
    }
}

sub routes() is export {
    my %storage;
    route {
        before MyBasicAuth.new;
        post -> LoggedInUser $user, 'api' {
            request-body -> %json-object {
                my $uuid = UUID.new(:version(4));
                %storage{$uuid} = %json-object;
                created "api/$uuid", 'application/json', %json-object;
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Эта структура:

route {
    before MyBasicAuth.new;
    post -> LoggedInUser $user, 'api' {
        ...
    }
}

Зависит от новой семантики before / after в следующей версии Cro 0.8.0. В текущем выпуске Cro на момент запроса / записи - и предшествующих ему - before в блоке route будет применяться только к маршрутам, которые уже были сопоставлены. Однако это было слишком поздно для промежуточного программного обеспечения, которое должно было повлиять на то, что будет соответствовать . Способ сделать это до Cro 0.8.0 - это либо смонтировать промежуточное ПО на уровне сервера, либо сделать что-то вроде этого:

route {
    before MyBasicAuth.new;
    delegate <*> => route {
        post -> LoggedInUser $user, 'api' {
            ...
        }
    }
}

Что обеспечивает применение промежуточного программного обеспечения перед рассмотрением любого соответствия маршрута. Это не так красиво, поэтому изменения в предстоящем 0.8.0 (который также представит before-matched с оригинальной семантикой before).

Наконец, forbidden without $success; здесь не сработает. Подпрограмма forbidden является частью Cro::HTTP::Router и предназначена для использования в обработчиках маршрутизации, тогда как промежуточное ПО не привязано к маршрутизатору (так что вы можете решить направлять запросы другим способом, например, не теряя возможности использовать все промежуточное программное обеспечение). Контракт метода authenticate заключается в том, что он возвращает истинное значение, определяющее, что должно произойти; это не подходящее место, чтобы попытаться использовать другой код ответа.

Ошибка соответствия ограничения авторизации, например LoggedInUser, приведет к 401. Чтобы переписать это, добавьте after в самый внешний блок route, чтобы отобразить его:

route {
    before MyBasicAuth.new;
    after { forbidden if response.status == 401; }
    delegate <*> => route {
        post -> LoggedInUser $user, 'api' {
            ...
        }
    }
}
0 голосов
/ 31 октября 2018

Похоже, в настоящее время в версии кро выпуска есть ошибка, которая уже исправлена ​​в апстриме на github . С помощью sena_kun из IRC-канала # perl6 мы использовали текущую версию cro-http:

$ git clone https://github.com/croservices/cro-http.git
$ perl6 -Icro-http/lib example.p6

А потом с curl я наконец увидел "аутентификацию под названием". Мы обнаружили еще две маленькие ошибки:

first one: Когда я вызывал curl -v -d '{"string":"hi"}' http://admin:secret@localhost:10000/api, я забыл добавить -H 'Content-Type: application/json'

authentication called An operation first awaited:   in sub request-body at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 716   in block  at restapp/example.pl line 24 in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 130

Died with the exception:
    Cannot unbox a type object (Nil) to int.
      in sub decode-payload-to-pairs at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/BodyParsers.pm6 (Cro::HTTP::BodyParsers) line 62
      in method parse at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/BodyParsers.pm6 (Cro::HTTP::BodyParsers) line 50
      in method body at /home/martin/.rakudobrew/moar-2018.08/install/share/perl6/site/sources/557D6C932894CB1ADE0F83C0596851F9212C2A67 (Cro::MessageWithBody) line 77
      in sub request-body at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 716
      in block  at restapp/example.pl line 24
      in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 130

второй один был из-за вызова forbidden в этой части:

class MyBasicAuth does Cro::HTTP::Auth::Basic[MyUser, "username"] {
    method authenticate(Str $user, Str $pass --> Bool) {
        say "authentication called";
        my $success = $user eq 'admin' && $pass eq 'secret';
        forbidden unless $success;
        return $success;
    } }

Что приводит к этой трассировке стека:

authentication called
Can only use 'content' inside of a request handler
  in sub set-status at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 846
  in sub forbidden at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router) line 823
  in method authenticate at restapp/example.pl line 15
  in method process-auth at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Auth/Basic.pm6 (Cro::HTTP::Auth::Basic) line 26
  in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Auth/Basic.pm6 (Cro::HTTP::Auth::Basic) line 11
  in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Auth/Basic.pm6 (Cro::HTTP::Auth::Basic) line 8
  in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/Internal.pm6 (Cro::HTTP::Internal) line 22
  in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/RequestParser.pm6 (Cro::HTTP::RequestParser) line 109
  in block  at /home/martin/.workspace/voteimproved/cro-http/lib/Cro/HTTP/RequestParser.pm6 (Cro::HTTP::RequestParser) line 90
  in block  at /home/martin/.rakudobrew/moar-2018.08/install/share/perl6/site/sources/F048BB66854D2463798A39CC2B01D4CC1532F957 (Cro::TCP) line 53

Я думаю, что эти ошибки будут исправлены в ближайшее время!

...