9

我正在寻找一个简单的解决方案来使用 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;
            }
        }
    }
}
4

2 回答 2

6

这种结构:

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

取决于即将到来的 Cro 0.8.0 中的新before/after语义。在询问/写作时的当前 Cro 版本中 - 以及之前的版本 -before一个route块中将仅适用于已经匹配的路由。但是,对于旨在影响匹配内容的中间件而言,这为时已。在 Cro 0.8.0 之前执行此操作的方法是在服务器级别安装中间件,或者执行以下操作:

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

这确保在考虑任何路由匹配之前应用中间件。这不是那么漂亮,因此即将到来的 0.8.0 中的变化(这也将引入before-matched具有原始before语义的 a)。

最后,forbidden without $success;是不会在这里工作。sub 是路由处理程序的forbidden一部分Cro::HTTP::Router并用于路由处理程序,而中间件不绑定到路由器(因此您可以决定以不同的方式路由请求,例如,而不会失去使用所有中间件的能力)。该authenticate方法的约定是它返回一个确定应该发生什么的真实值;这不是尝试强制使用不同响应代码的合适位置。

未能匹配 auth 约束LoggedInUser将产生 401。要重写它,after请在最外面的route块中添加一个来映射它:

route {
    before MyBasicAuth.new;
    after { forbidden if response.status == 401; }
    delegate <*> => route {
        post -> LoggedInUser $user, 'api' {
            ...
        }
    }
}
于 2018-10-31T10:18:41.000 回答
3

目前 cro 发布版本中似乎存在一个错误,该错误已在github的上游修复。在#perl6 IRC 频道的 sena_kun 的帮助下,我们确实使用了当前版本cro-http

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

然后curl我终于看到了“认证调用”。我们发现了另外两个小错误:

一个:当我调用时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

我认为这个错误很快就会被修复!

于 2018-10-31T08:23:22.897 回答