【问题标题】:How can I use NTLM or Kerberos authentication with Mojo::UserAgent如何通过 Mojo::UserAgent 使用 NTLM 或 Kerberos 身份验证
【发布时间】:2015-09-22 06:42:07
【问题描述】:

我正在尝试让 Mojo::UserAgent 通过 NTLM 进行身份验证。大致是这样的:

use Mojo::UserAgent;
use Mojo::URL;
use Data::Dump qw/dump/;
use Path::Tiny;
use Authen::NTLM;

$\ = "\n"; $|++;

my $ntlm = Authen::NTLM-> new(host => "some.hidden.pl", user => 'foo',
              domain   => "bar", password => "baz", version  => 2);

my $xml = path($ARGV[0])->slurp;

my $ua = Mojo::UserAgent->new;
my $url = Mojo::URL->new('https://some.hidden.pl/ews/exchange.asmx');

$url->userinfo(sprintf('%s\%s:%s', qw/bar foo baz/));

my $tx = $ua->get($url);

my $tx = $ua->build_tx(GET => $url);
$challenge = $ntlm->challenge;
$tx->req->headers->header('Authorization' => 'NTLM ' . $challenge);
$ua->start($tx);

$challenge = [ split /,\s*/, $tx->res->headers->header('www-authenticate') ]->[0] =~ s/NTLM //r;
$challenge = $ntlm->challenge($challenge);
my $tx = $ua->build_tx(GET => $url);
$tx->req->headers->header('Authorization' => 'NTLM ' . $challenge);
$ua->start($tx);

$tx = $ua->build_tx(POST => $url, {'Content-Type' => 'text/xml'}, $xml );
$tx->req->headers->content_type('text/xml');
$tx->req->headers->header('Authorization' => 'NTLM ' . $challenge);
$ua->start($tx);
print dump $tx->res;

但我在服务器第二次响应时不断收到 401。

我做错了什么?使用 Kerberos 身份验证是否更容易(如果是,如何使用)?

谢谢

【问题讨论】:

  • 您是否考虑过 curl 作为替代方案?
  • 我在 bash 脚本中尝试过 curl - 就像一个魅力。 perl 库的学习曲线有点陡峭。我也尝试过使用 ntlm auth 的 LWP::UserAgent,但失败了。由于这是 Mojolicious 应用程序的一部分,我想尝试并坚持使用 Mojo::UserAgent。我也会尝试 WWW::Mechanize 和 LWP::Protocol::Net::Curl。
  • 有一个SPNEGO pluginfür LWP,我报告了一些错误,但作者拒绝修复它们。我不会用它。
  • 您有使用 curl --debug 的工作会话吗?你能注意到它与标题有何不同... mojo 返回?
  • 是的,并且 curl 工作正常。发送的第一个标头是相同的,但随后的标头不同 - 如果我没记错的话,包括从服务器返回的第一个挑战(我现在不在工作)

标签: perl ntlm mojolicious


【解决方案1】:

我刚刚发布了一个新模块,在这方面应该很有帮助Mojolicious::Plugin::SPNEGO。使用起来非常简单:

use Mojolicious::Lite;

my $SERVER = 'my-ad-server.example.com';

app->secrets(['My secret passphrase here']);

plugin 'SPNEGO', ad_server => $SERVER;

get '/' => sub {
   my $c = shift;
   if (not $c->session('user')){
       $c->ntlm_auth({
           auth_success_cb => sub {
               my $c = shift;
               my $user = shift;
               my $ldap = shift; # bound Net::LDAP::SPNEGO connection
               $c->session('user',$user->{samaccountname});
               $c->session('name',$user->{displayname});
               my $groups = $ldap->get_ad_groups($user->{samaccountname});
               $c->session('groups',[ sort keys %$groups]);
               return 1;
           }
       }) or return;
   }
} => 'index';

app->start;

__DATA__

@@ index.html.ep
<!DOCTYPE html>
<html>
<head>
<title>NTLM Auth Test</title>
</head>
<body>
<h1>Hello <%= session 'name' %></h1>
<div>Your account '<%= session 'user' %>' belongs to the following groups:</div>
<ul>
% for my $group (@{session 'groups' }) {
   <li>'<%= $group %>'</li>
% }
</ul>
</body>
</html>

该模块基于同样新发布的 Net::LDAP::SPNEGO 模块,该模块为 SPNEGO 对话框提供基本构建块。

【讨论】:

  • 谢谢!这将如何与 Exchange Web 服务一起使用?或者您对如何为我的组织找到广告服务器有什么建议?
  • 多么漂亮的解决方案和插件@TobiOetiker 有没有办法指定 basedn,或者我应该只依赖广告组?
  • 你可以在对象中指定baseDN,否则它会向rootDSE询问'defaultnamingcontext'Net::LDAP::SPNEGO-&gt;new($SERVER,baseDN=&gt;....);注意你可以用'Net::LDAP'做的所有事情你也可以做使用 Net::LDAP::SPNEGO。
猜你喜欢
  • 2014-08-18
  • 1970-01-01
  • 2011-03-25
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
相关资源
最近更新 更多