首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

Catalyst 应用中实现用户本地和域校验混合

作者:  时间: 2010-10-24
#
#
# Catalyst 应用中实现用户本地和域校验集成, 且可自动添加域用户
#
#

package MyApp::Authentication::Store::DBIx::Class::User;

=head2 Example

# username_field : username
# password_field : password 

__PACKAGE__->config = {
    ...
    'Plugin::Authentication' => {
        default => {
            auto_create_user => 1,

            credential => {
                class => 'Password',               password_type => 'self_check',
                password_field => 'password'
            },
           store => {
                class => 'DBIx::Class',
                ...
                store_user_class =>
    'MyApp::Authentication::Store::DBIx::Class::User',
                domain_host => '127.0.0.1:389',
                domain_name => 'domain.com'
            }
        }
    }
}

=cut

use Moose;
use namespace::autoclean;

use Net::LDAP;
use Digest::MD5 qw(md5_hex);

extends qw/Catalyst::Authentication::Store::DBIx::Class::User/;

sub check_password {
    my ( $self, $password ) = @_;
    
    # check password by field password
    return ( $self->_user->password
                eq md5_hex( $password ) ) ? 1 : 0
                        if !$self->_user->authen_domain;

    # check password by windows domain
    my $ldap;
    # connect ad server and check password
    if ( !$self->config->{'domain_host'}
      || !$self->config->{'domain_name'}
      || ! ( $ldap = Net::LDAP->new(
                        $self->config->{'domain_host'},
                        timeout => 20  ) ) ) {
        return 0;
    }
    # try to login to ad
    my $msg = $ldap->bind(
                        join( '@', 
                              $self->_user->username,
                              $self->config->{'domain_name'}
                        ),
                        password => $password
                     );
    # check return code
    if ( !$msg->is_error()
      || $msg->server_error =~ 
                / AcceptSecurityContext error, data 53[0-3],/is ) {
        $self->_user($self->_user->update_or_insert());
        return 1;
    }
    warn "*** Password check failed : ", $msg->error(), "\n";
    return 0;
}

around 'auto_create' => sub  {
    my ( $orig, $self, $authinfo ) = @_;
    
    my $username = $authinfo->{username};
    
    $self->_user( $self->resultset->new_result( {
                                username => $username,
                                password => '',
                                authen_domain => 1
                        } )
        );
    
    return $self;
};

1;