perl6中的基本身份验证与Cro

Mar*_*rth 9 basic-authentication perl6 cro

我正在寻找一个简单的解决方案来保护我的路线与基本认证机制与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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ton 6

这个结构:

route {
    before MyBasicAuth.new;
    post -> LoggedInUser $user, 'api' {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

取决于即将推出的Cro 0.8.0中的新before/ after语义.在当前的Cro发布时,在询问/写入时 - 以及之前的那些 - before在一个route块中将仅适用于已经匹配的路由.然而,这对中间件是为了碰撞出怎样太晚匹配.在Cro 0.8.0之前执行此操作的方法是在服务器级别安装中间件,或者执行以下操作:

route {
    before MyBasicAuth.new;
    delegate <*> => route {
        post -> LoggedInUser $user, 'api' {
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

最后,forbidden without $success;不会在这里工作.该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' {
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)