Mercurial > pub > Impl
changeset 73:2f31ecabe9ea
doc
security
author | wizard |
---|---|
date | Mon, 29 Mar 2010 06:56:05 +0400 |
parents | eac47fa4f262 |
children | 84aa8c395fce |
files | Lib/IMPL/Config.pm Lib/IMPL/Object/Factory.pm Lib/IMPL/Security.pm Lib/IMPL/Security/Auth.pm Lib/IMPL/Security/Auth/Simple.pm Lib/IMPL/Security/Role.pm Lib/IMPL/Web/Application.pm Lib/IMPL/Web/QueryHandler/AuthCookie.pm Lib/IMPL/Web/QueryHandler/SecureCookie.pm Lib/IMPL/Web/Security.pm Lib/IMPL/Web/Security/Embed.pm Lib/IMPL/Web/Security/Session.pm _doc/make.pl |
diffstat | 13 files changed, 358 insertions(+), 135 deletions(-) [+] |
line wrap: on
line diff
--- a/Lib/IMPL/Config.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Config.pm Mon Mar 29 06:56:05 2010 +0400 @@ -118,28 +118,34 @@ =pod -=h1 SYNOPSIS +=head1 NAME + +C<IMPL::Config> - базовый класс для настраиваемого приложения. + +=head1 SYNOPSIS -package App::Config -use base qw(IMPL::Config) +=begin code + +# define application + +package MyApp; +use base qw(IMPL::Config); use IMPL::Class::Property; use IMPL::Config::Class; BEGIN { public property SimpleString => prop_all; - public property MyClass => prop_all; public property DataSource => prop_all; } sub CTOR { my $this = shift; - - $this->MyClass(new IMPL::Config::Class(Type => 'MyClass'')) unless $this->MyClass; + $this->DataSource( new IMPL::Config::Activator( - type => 'MyDataSource', - args=>{ + factory => 'MyDataSource', + parameters=>{ host => 'localhost', user => 'dbuser' } @@ -147,37 +153,85 @@ ) unless $this->Exists('DataSource'); } -# in some script +# using application object -my $app = spawn App::Config('default.xml'); +my $app = spawn MyApp('default.xml'); $app->Run(); +=end code + +Ниже приведен пример файла C<default.xml> содержащего настройки приложения + +=begin code xml + +<app type='MyApp'> + <SimpleString>The application</SimpleString> + <DataSource type='IMPL::Config::Activator'> + <factory>MyDataSourceClass</factory> + <parameters type='HASH'> + <host>localhost</host> + <user>dbuser</user> + </parameters> + </DataSource> +</app> + +=end code xml + =head1 DESCRIPTION -Позволяет сохранить/загрузить конфигурацию. Также все классы конфигурации -должны наследоваться от данного класса, и все Public свойства будут -автоматически сохраняться и восстанавливаться. +C<[Serializable]> + +C<[Autofill]> + +C<use base IMPL::Object::Accessor> + +Базовый класс для приложений. Использует подход, что приложение +является объектом, состояние которого предтавляет собой конфигурацию, +а методы - логику. + +Данный класс реализует функционал десериализации (и сериализации) экземпляра +приложения из XML документа. Для этого используется механизм C<IMPL::Serialization>. +При этом используются опции C<IMPL::Serialization::XmlFormatter> C<IdentOutput> и +C<SkipWhitespace> для записи документа в легко читаемом виде. + +Поскольку в результате восстановления приложения восстанавливаются все элементы +из файла конфигурации, то это может потребовать значительных ресурсов для +создания частей, которые могут никогда не понадобиться. Например, не требуется инициализация +источника данных для передачи пользователю статических данных, сохраненных на диске. + +Для решения этой проблемы используются специальные объекты C<IMPL::Config::Activator>. + +Если у приложения описано свойство, в котором хранится C<IMPL::Config::Activator>, то +при первом обращении к такому свойству, будет создан объект вызовом метода +C<< IMPL::Config::Activator->activate() >> и возвращен как значение этого свойства. +Таким образом реализуется прозрачная отложенная активация объектов, что позволяет +экономить ресурсы. =head1 MEMBERS =over -=item C<< IMPL::Config->LoadXMLFile($fileName) >> +=item C<[static] LoadXMLFile($fileName) > -Создает из XML файла экземпляр приложения +Создает из XML файла C<$fileName> экземпляр приложения -=item C<< $instance->SaveXMLFile($fileName) >> +=item C<SaveXMLFile($fileName)> -Сохраняет приложение в файл +Сохраняет приложение в файл C<$fileName> + +=item C<[get] xml > -=item C<< xml >> +Сохраняет конфигурацию приложения в XML строку. -Сохраняет конфигурацию приложения в XML строку +=item C<[static,operator] spawn($file)> -=item C<< IMPL::Config->spawn($file) >> +Синоним для C<LoadXMLFile>, предполагается использование как оператора. -Синоним для C<LoadXMLFile> +=item C<rawGet($propname,...)> + +Метод для получения значений свойств приложения. Данный метод позволяет избежать +использование активации объектов через C<IMPL::Config::Activator>. =back
--- a/Lib/IMPL/Object/Factory.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Object/Factory.pm Mon Mar 29 06:56:05 2010 +0400 @@ -7,7 +7,8 @@ BEGIN { public property factory => prop_get | owner_set; - public property parameters => prop_get | owner_set; + public property parameters => prop_get | owner_set; + public property method => prop_get | owner_set; } # custom factory, overrides default @@ -18,10 +19,11 @@ } sub CTOR { - my ($this,$factory,$parameters) = @_; + my ($this,$factory,$parameters,$method) = @_; $this->factory($factory) or die new IMPL::InvalidArgumentException("The argument 'factory' is mandatory"); $this->parameters($parameters) if $parameters; + $this->method($method) if $method; } # override default restore method @@ -41,7 +43,11 @@ sub CreateObject { my $this = shift; - return $this->factory->new($this->parameters ? (_as_list($this->parameters),@_) : @_); + if (my $method = $this->method) { + $this->factory->$method($this->parameters ? (_as_list($this->parameters),@_) : @_); + } else { + $this->factory->new($this->parameters ? (_as_list($this->parameters),@_) : @_); + } } sub _as_list { @@ -122,9 +128,9 @@ =over -=item C< CTOR($factory,$parameters) > +=item C< CTOR($factory,$parameters,$method) > -Создает новый экземпляр +Создает новый экземпляр фабрики. =over @@ -145,6 +151,11 @@ Если является любым другим объектом или скаляром, то будет передан параметром методу C<new> как есть. +=item C<$method> + +Имя метода (или ссылка на процедуру), который будет вызван у C<$factory> при создании +текущей фабрикой нового объекта. + =back =item C< [get] factory > @@ -168,7 +179,9 @@ sub new { my ($this,@params) = @_; - return $this->factory->new(_as_list($this->parameters), @params); + my $method = $this->method || 'new'; + + return $this->factory->$method(_as_list($this->parameters), @params); } =end code
--- a/Lib/IMPL/Security.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Security.pm Mon Mar 29 06:56:05 2010 +0400 @@ -22,6 +22,16 @@ die new IMPL::NotImplementedException(); } +sub MakeContext { + my ($this,$principal,$refRoles,$auth) = @_; + + return new IMPL::Security::Context( + principal => $principal, + rolesAssigned => $refRoles, + auth => $auth + ); +} + sub Rules { return \@rules; } @@ -129,6 +139,26 @@ =back +=item C<MakeContext($principal,$role,$auth)> + +Создает контекст безопасности, инициализируя его передданными параметрами. + +=over + +=item C<$principal> + +Объект пользователя + +=item C<$role> + +Роль или ссылка на массив ролей + +=item C<$auth> + +Объект аутентификации + +=back + =item C<Take($principal,$role)> Метод. Делегирует текущему пользователю полномочия другого пользователя. При этом выполняется проверка @@ -150,7 +180,7 @@ =back -=item C<Roles()> +=item C<Rules()> Возвращает список правил которые выполняются при проверках доступа. Пререопределите этот метод, чтобы возвращать собственный список правил. Список правил является ссылкой на массив
--- a/Lib/IMPL/Security/Auth.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Security/Auth.pm Mon Mar 29 06:56:05 2010 +0400 @@ -28,6 +28,10 @@ die new IMPL::NotImplementedException; } +sub isTrusted { + 0; +} + 1; __END__ @@ -86,6 +90,10 @@ Создает пакет для авторизации на основе данных безопасности для пользователя. C<$SecData> - Зависит от пакета аутентификации. +=item C<[get] isTrusted> + +Флаг того, что аутентификация закончена успешно. + =item C<DoAuth($Challenge)> Производит аутентификацию пользователя и инициализацию сессии, @@ -103,6 +111,8 @@ =item C<[static] SecDataArgs()> Возвращает хеш с описанием параметров для функции C<CreateSecData>. Ключами являются -имена параметров, значениями - типы. +имена параметров, значениями - типы. + +=back =cut \ No newline at end of file
--- a/Lib/IMPL/Security/Auth/Simple.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Security/Auth/Simple.pm Mon Mar 29 06:56:05 2010 +0400 @@ -80,7 +80,28 @@ Результат либо C<AUTH_SUCCESS>, либо C<AUTH_FAIL> -=item +=item C<$challenge> + +В случае успеха возвращает cookie (уникальный номер) сессии + +=back + +=item C<ValidateSession($challenge)> + +Проверяет аутентичность сессии. Использует один этап. C<$challenge> cookie +сессии, полученный при выполнении метода C<DoAuth>. + +Возвращает C<($status,$challenge)> + +=over + +=item C<$status> + +Результат либо C<AUTH_SUCCESS>, либо C<AUTH_FAIL> + +=item C<$challenge> + +Всегда C<undef> =back
--- a/Lib/IMPL/Security/Role.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Security/Role.pm Mon Mar 29 06:56:05 2010 +0400 @@ -5,8 +5,8 @@ use IMPL::Class::Property; BEGIN { - public property roleName => prop_get; - public property parentRoles => prop_get; + public property roleName => prop_get | owner_set; + public property parentRoles => prop_get | owner_set | prop_list; } sub CTOR { @@ -39,20 +39,24 @@ =pod +=head1 NAME + +C<IMPL::Security::Role> Роль + =head1 DESCRIPTION -Роль. Может включать в себя базовые роли. +Может включать в себя базовые роли. Имеется метод для проверки наличия необходимых ролей в текущей роли. =head1 MEMBERS =over -=item C<roleName> +=item C<[get] roleName> Имя роли, ее идентификатор -=item C<parentRoles> +=item C<[get,list] parentRoles> Список родительских ролей
--- a/Lib/IMPL/Web/Application.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Web/Application.pm Mon Mar 29 06:56:05 2010 +0400 @@ -17,16 +17,10 @@ public property actionFactory => prop_all; public property handlersQuery => prop_all | prop_list; public property responseCharset => prop_all; + public property security => prop_all; public property options => prop_all; } -# custom factory -sub new { - my ($self,$file) = @_; - - return $self->LoadXMLFile($file); -} - sub CTOR { my ($this) = @_; @@ -84,6 +78,8 @@ =head1 DESCRIPTION +C< use base qw( IMPL::Config IMPL::Object::Singleton )> + Зкземпляр приложения содержит в себе глобальные настройки, реализует контроллер запросов, в качестве источника запросов используется CGI или иной совместимый модуль. @@ -180,3 +176,47 @@ =end code xml +=head1 MEMBERS + +=over + +=item C<[get,set] handlerError> + +Обработчик который будет вызван в случае возникновения необработанной ошибки +в процессе работы приложения. После чего приложение корректно завершается. + +=item C<[get,set] actionFactory> + +Фабрика объектов, которая используется приложением, для создания объектов +типа C<IMPL::Web::Application::Action> при обработки C<CGI> запросов. + +=begin code + +my $action = $this->actionFactory->new( + query => $query, + application => $this, +); + +=end code + +=item C< [get,set,list] handlersQuery > + +Список обработчиков запросов, которые будут переданы созданному объекту-действию. + +=item C< [get,set] responseCharset> + +Кодировка ответа клиенту. + +=item C< [get,set] security > + +Объект C<IMPL::Web::Security>, для работы с инфраструктурой безопасности. + +=item C< [get,set] options > + +Обычно ссылка на хеш с настраиваемыми объектами, используется для возможности +програмной настройки активаторов, т.к. напрямую через свойства приложения получить +к ним доступ не получится. + +=back + +=cut \ No newline at end of file
--- a/Lib/IMPL/Web/QueryHandler/AuthCookie.pm Fri Mar 26 16:26:31 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -package IMPL::Web::QueryHandler::AuthCookie; - -use base qw(IMPL::Web::QueryHandler); -use Digest::MD5 qw(md5_hex); - -use IMPL::Class::Property; -use IMPL::Security::Auth qw(:Const); - -BEGIN { - public property salt => prop_all; -} - -sub CTOR { - my ($this) = @_; - - -} - -sub Process { - my ($this,$action,$nextHandler) = @_; - - my $method = $action->query->cookie('method') || 'simple'; - - if ($method eq 'simple') { - - my $sid = $action->query->cookie('sid'); - - if ($action->query->cookie('sign') eq md5_hex( - $this->salt, - $sid, - $this->salt - ) ) { - - my $context = $action->application->security->Session( - id => $sid, - method => 'simple' - ); - - my ($result,$challenge) = $context->auth->ValidateSession($sid); - - if ($result == AUTH_SUCCESS) { - return $context->Impersonate($nextHandler); - } else { - return $nextHandler->(); - } - } - } else { - die new IMPL::Exception("Unknown auth method",$method); - } -} - - -1; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/Web/QueryHandler/SecureCookie.pm Mon Mar 29 06:56:05 2010 +0400 @@ -0,0 +1,52 @@ +package IMPL::Web::QueryHandler::SecureCookie; + +use base qw(IMPL::Web::QueryHandler); +use Digest::MD5 qw(md5_hex); + +use IMPL::Class::Property; +use IMPL::Security::Auth qw(:Const); + +BEGIN { + public property salt => prop_all; +} + +sub CTOR { + my ($this) = @_; + + +} + +sub Process { + my ($this,$action,$nextHandler) = @_; + + my $method = $action->query->cookie('method') || 'simple'; + + if ($method eq 'simple') { + + my $sid = $action->query->cookie('sid'); + + if ($action->query->cookie('sign') eq md5_hex( + $this->salt, + $sid, + $this->salt + ) ) { + + my $context = $action->application->security->Session( + id => $sid + ); + + my ($result,$challenge) = $context->auth->ValidateSession($sid); + + if ($result == AUTH_SUCCESS) { + return $context->Impersonate($nextHandler); + } else { + return $nextHandler->(); + } + } + } else { + die new IMPL::Exception("Unknown auth method",$method); + } +} + + +1; \ No newline at end of file
--- a/Lib/IMPL/Web/Security.pm Fri Mar 26 16:26:31 2010 +0300 +++ b/Lib/IMPL/Web/Security.pm Mon Mar 29 06:56:05 2010 +0400 @@ -1,29 +1,72 @@ package IMPL::Web::Security; +use base qw(IMPL::Object IMPL::Security IMPL::Object::Autofill); + +use IMPL::Class::Property; + +__PACKAGE__->PassThroughArgs; + +BEGIN { + public property sessionFactory => prop_get | owner_set; + public property userFactory => prop_get | owner_set; +} + +sub CTOR { + my ($this) = @_; + + $this->dataSource or die new IMPL::InvalidArgumentException("The argument is required",'dataSource'); +} + +sub Session { + my ($this,%args) = @_; +} + +sub User { + +} + 1; __END__ =pod +=head1 NAME + +C<IMPL::Web::Security> Модуль для аутентификации и авторизации веб запроса. + +=head1 SINOPSYS + +=begin code xml + +<security type='IMPL::Config::Activator'> + <factory>IMPL::Web::Security</factory> + <parameters type='HASH'> + <sessionFactory type='IMPL::Object::Factory'> + <factory type='IMPL::Object::Factory'>App::Data::Session</factory> + <method>insert</method> + </sessionFactory> + </parameters> +</security> + +=end code xml + =head1 DESCRIPTION -Модуль для аутентификации и авторизации веб запроса. - -Получает запрос, вычленяет из него информацию для авторизации, производит авторизацию пользователя -и создает контекст безопасности. - -При этом использует указанные модули аутентификации. - -Информацию для аутентификации модуль получает через соответствующие адаптеры. +Отвечает за инфраструктуру аутентификации и авторизации запросов. Основная особенность +заключается в том, что запросы приходят через значительные интевалы времени, хотя и +относятся к одной логической транзакции. В промежутках между запросами сервер не +сохраняет свое состояние. Поэтому при каждом обращении сервер восстанавливает +контекст безопасности. -=item C<IMPL::Web::Security::Server> - -Аутентифицирует пользователя на основе данных, предоставленных сервером +C<IMPL::Web::Session> Объект обеспечивающий сохранение состояния в рамках одной сессии +пользователя. Кроме контекста безопасности хранит дополнительние данные, которые необходимо +сохранить между обработкой запросов. -=item C<IMPL::Web::Security::Embed> +C<IMPL::Web::User> Объект, устанавливающий связь между идентификатором пользователя +C<IMPL::Security::Principal>, его ролями и данными безопасности для создания объектов +аутентификации C<IMPL::Security::Auth>. -Аутентифицирует пользователя используя указанные модули, при этом получает данные -из запроса. +=head1 MEMBERS =cut \ No newline at end of file
--- a/Lib/IMPL/Web/Security/Embed.pm Fri Mar 26 16:26:31 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -package IMPL::Web::Security::Embed; - -use base qw(IMPL::Object); - -1; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/Web/Security/Session.pm Mon Mar 29 06:56:05 2010 +0400 @@ -0,0 +1,14 @@ +package IMPL::Web::Security::Session; + +use base qw(IMPL::Object); + +use IMPL::Class::Property; + +__PACKAGE__->PassThroughArgs; + +BEGIN { + public property id => prop_all; + public property securityContext => prop_all; +} + +1; \ No newline at end of file
--- a/_doc/make.pl Fri Mar 26 16:26:31 2010 +0300 +++ b/_doc/make.pl Mon Mar 29 06:56:05 2010 +0400 @@ -158,31 +158,31 @@ sub view_seq_link { my ($self,$text) = @_; - if ($text =~ /^\s*(?:(\w+)\s+)?(\w+(?:\:\:\w+)+)\s*$/) { + $text =~ s/(\w+(?:\:\:\w+)+)/ + if (my $url = $self->mk_filelink($1)) { + "<a href='$url'>$1<\/a>"; + } else { + $1; + } + /gex; - my ($keyword, $package) = ($1 || '',$2); - - my @path = split /::/, $package; - - pop @path if $keyword; - shift @path if uc $path[0] eq 'IMPL'; - + return "<code>$text</code>"; +} + +sub mk_filelink { + my ($self,$package) = @_; + + return undef unless $package; + + my @path = split /::/, $package; + + if ($path[0] eq 'IMPL') { + shift @path; if (-f File::Spec->catfile($LibDir,@path).".pm") { - return '<code><a href="'. '../'x($level-1) . File::Spec->catfile(@path) .'.html">'.$text.'</a></code>'; - } - - } elsif ($text =~ /^\s*(\w+(?:\:\:\w+)+)\s*->\s*(\w+)\s*$/) { - my ($package,$member) = ($1,$2); - - my @path = split /::/, $package; - shift @path; - - if (-f File::Spec->catfile($LibDir,@path).".pm") { - return '<code><a href="'. '../'x($level-1) . File::Spec->catfile(@path) .'.html">'.$text.'</a></code>'; + return '../'x($level-1) . File::Spec->catfile(@path).'.html'; } } - - return "<code>$text</code>"; + return undef; } sub view_seq_code {