如何从 Mojolicious 应用程序的命令行获取凭据? [英] How can I take credentials from the command line in a Mojolicious app?

查看:70
本文介绍了如何从 Mojolicious 应用程序的命令行获取凭据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Mojolcious 独立应用程序.在代码中,我正在联系一个内部后端,用户应该在其中提供一些凭据.

I am developing a Mojolcious standalone application. In the code I am contacting an internal backend where the user should provide some credentials.

目前我使用代码中的凭据作为变量.它看起来有点像:

Currently I am using the credentials inside the code as variables. It looks some something like:

$password = 'somthing';

我尝试使用配置插件将凭据存储在那里,但是 Mojolicious 是否有一个选项可以让用户在运行守护程序时提供他的凭据?也许喜欢:

I tried to use the config plugin to store the credentials there, but is there an option with Mojolicious to let the user provide his credentials when running the daemon? Maybe like:

perl myapp.pl daemon -user username -password password

Mojolicious 处理此用例的最佳策略是什么?

What is the best strategy with Mojolicious to handle this use case?

推荐答案

对于这个问题,我将提供两种解决方案.一个相当简单,而另一个使用一些高级技术.

I will provide two solutions to this problem. One is rather easy while the other one uses a few advanced techniques.

您可以在启动应用时简单地将环境变量传递给它.

You can simply pass environment variables to your app when you start it.

$ USERNAME=foo PASSWORD=bar perl app.pl daemon

Mojolicious 是 Perl,所以它们以 %ENV 结尾.我们可以使用 $ENV{USERNAME}$ENV{PASSWORD} 访问它们.通常这些环境变量都是大写的.选择特定于应用程序的内容是有意义的,因此 MYAPP_USERNAME 可能比 USERNAME 更好.

Mojolicious is Perl, so they end up in %ENV. We can access them with $ENV{USERNAME} and $ENV{PASSWORD}. Typically those environment variables are all-caps. It would make sense to pick something app-specific, so MYAPP_USERNAME is probably a better choice than USERNAME.

这样做的好处是你也可以在你的 shell 环境中设置它,然后你就不用担心它了.

The good thing about this is that you can also set it in your shell environment and then you never have to worry about it.

package MyApp;
use Mojolicious::Lite;
use Data::Printer;

helper( 
    credentials => sub { 
        state $credentials = { 
            username => $ENV{USERNAME}, 
            password => $ENV{PASSWORD}, 
        } 
    }
);

get '/' => sub {
    my $c = shift;
    $c->render( text => np $c->app->credentials );
};

app->start;

在上面的示例中,我创建了一个 helper 为我们保留凭据,以便轻松访问它们.当然,您可以在整个代码中使用 $ENV{USERNAME},但我认为将其正确封装会更好.

In the above example I have created a helper that keeps the credentials for us so it's easy to access them. Of course you could just use $ENV{USERNAME} throughout the code, but I believe it's nicer to have it properly encapsulated.

如果我们 curl localhost:3000 守护进程,我们会得到这个输出.

If we curl localhost:3000 the daemon we get the this output.

$ curl localhost:3000
\ {
    password   "bar",
    username   "foo"
}

高级:子类化 daemon 命令

命令行参数全部由 Mojolicious::Command 处理.

您可以创建自己的 Mojolicious::Command 子类.这在 Mojolicious 中有记录::食谱.如果你将它命名为 Mojolicious::Command::foo 那么你甚至不需要担心为 Mojo 添加另一个命名空间来查找命令.

You can create your own Mojolicious::Command subclass. This is documented in the Mojolicious::Cookbook. If you name it Mojolicious::Command::foo then you don't even need to worry about adding another namespace for Mojo to look for commands in.

但不幸的是,您不能同时传递多个命令.所以创建一个子类 credentials 然后这样做是行不通的.

But you can unfortunately not pass several commands at the same time. So creating a subclass credentials and then doing this does not work.

$ perl myapp.pl daemon credentials --username foo --password bar

所以我们需要做一些其他的事情.快速浏览Mojolicious::Command::daemon 告诉我们它只有 run 方法,该方法在调用该命令时会自动调用.我们希望它做一些额外的事情,所以我们子类化那个特定的命令.

So we need to do something else. A quick look at the Mojolicious::Command::daemon tells us that it only has the run method, which gets called automatically when that command is called. We want it to do something additional, so we subclass that specific command.

package Mojolicious::Command::mydaemon;
use Mojo::Base 'Mojolicious::Command::daemon';
use Mojo::Util 'getopt';

sub run {
    my ( $self, @args ) = @_;

    getopt
        'u|username=s' => \my $username,
        'p|password=s' => \my $password;

    $self->app->credentials->{username} = $username;
    $self->app->credentials->{password} = $password;

    return $self->SUPER::run;
}

我们需要导入 getopt,它可以帮助我们从命令行读取内容.我们将用户名和密码存储在 credentials 助手中,就像第一种方法一样,因为封装很好.

We need to import getopt, which helps us read stuff from the command line. We store the username and password in the credentials helper just like in the first approach because encapsulation is nice.

最后,我们需要交给原来的run方法.这是通过调用 $self->SUPER::run 来完成的,这是 Perl 在我继承的超类上说 call run 的方式.它在 SUPER:: 伪类上调用 run.您可以在 perlobj 中了解更多相关信息.

Finally, we need to hand over to the original run method. That's done by calling $self->SUPER::run, which is Perl's way of saying call run on my super-class from which I have inherited. It calls run on the SUPER:: pseudo class. You can learn more about that in perlobj.

现在实际的应用程序几乎相同.

Now the actual app is pretty much the same.

package MyApp;
use Mojolicious::Lite;
use Data::Printer;

helper(
    credentials => sub {
        state $credentials = { username => q{}, password => q{}, };
    }
);

get '/' => sub {
    my $c = shift;
    $c->render( text => np $c->app->credentials );
};

app->start;

我们是这样运行的:

$ perl code/scratch.pl mydaemon --username foo --password bar

如果我们curl localhost:3000,我们会得到相同的输出.

And if we curl localhost:3000 we get the same output.

$ curl localhost:3000
\ {
    password   "bar",
    username   "foo"
}

<小时>

您选择哪种方式取决于您.我不确定我自己更喜欢哪一种.两者各有千秋.


Which of those ways you choose is up to you. I am not sure which one I would prefer myself. Both have merits.

环境变量更容易实现,更便携,但代码不是很清楚.命令子类可以在正确完成时记录自己,但也许您的用户不会期望除了 daemon 之外的其他东西.还有更多的代码.

The environment variables are easier to implement and more portable, but the code is not as clear. The command subclass can document itself when done properly, but maybe your users would not expect something else than daemon. It's also a lot more code.

这篇关于如何从 Mojolicious 应用程序的命令行获取凭据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆