changeset 52:15d720913562

security in work
author wizard@linux-odin.local
date Tue, 02 Mar 2010 20:12:02 +0300
parents a1498298d3ee
children f4e045e47770
files Lib/IMPL/Class/Property/Direct.pm Lib/IMPL/Security/Auth.pm Lib/IMPL/Security/Auth/AuthResult.pm Lib/IMPL/Security/Auth/Simple.pm Lib/IMPL/Web/Application.pm Lib/IMPL/Web/Application/Action.pm Lib/IMPL/Web/Response.pm Lib/IMPL/Web/Security.pm
diffstat 8 files changed, 228 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/Class/Property/Direct.pm	Mon Mar 01 17:25:36 2010 +0300
+++ b/Lib/IMPL/Class/Property/Direct.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -22,8 +22,8 @@
 my $accessor_set_no = 'die new IMPL::Exception(\'The property is read only\',$name,$class) unless $set;';
 my $accessor_set = 'return( $this->{$field} = @_ == 1 ? $_[0] : [@_] );';
 my $accessor_get = 'return( $this->{$field} );';
-my $list_accessor_set = 'return( @{ ($this->{$field} = ( (@_ == 1 and ref $_[0] eq \'ARRAY\') ? $_[0] : [@_] ) || [] ) } );';
-my $list_accessor_get = 'return( @{ $this->{$field} || [] } );';
+my $list_accessor_set = 'return( @{ ($this->{$field} = IMPL::Object::List->new( ( (@_ == 1 and ref $_[0] eq \'ARRAY\') ? $_[0] : [@_] ) || [] ) } );';
+my $list_accessor_get = 'return( @{ $this->{$field} ? $this->{$field} : $this->{$field} = IMPL::Object::List->new() } );';
 my $custom_accessor_get = 'unshift @_, $this and goto &$get;';
 my $custom_accessor_set = 'unshift @_, $this and goto &$set;';
 
--- a/Lib/IMPL/Security/Auth.pm	Mon Mar 01 17:25:36 2010 +0300
+++ b/Lib/IMPL/Security/Auth.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -1,15 +1,24 @@
 package IMPL::Security::Auth;
 
+use Digest::MD5 qw(md5_hex);
+
 use constant {
-	SUCCESS => 1,
-	INCOMPLETE => 2,
-	FAIL => 3	
+	AUTH_SUCCESS => 1,
+	AUTH_INCOMPLETE => 2,
+	AUT_FAIL => 3	
 };
 
 use base qw(Exporter);
 
-our @EXPORT_OK = qw(&SUCCESS &INCOMPLETE &FAI);
-our %EXPORT_TAGS = (Const => [qw(&SUCCESS &INCOMPLETE &FAI)]);
+our @EXPORT_OK = qw(&AUTH_SUCCESS &AUTH_INCOMPLETE &AUTH_FAIL &GenSSID);
+our %EXPORT_TAGS = (Const => [qw(&AUTH_SUCCESS &AUTH_INCOMPLETE &AUTH_FAIL)]);
+
+{
+    my $i = 0;
+    sub GenSSID() {
+        return md5_hex(time,rand,$i++);
+    }
+}
 
 1;
 
@@ -33,4 +42,20 @@
 в которм содержится уникальные свойства сессии, например идентификатор, сеансовые ключи
 и т.д. 
 
+Пакет аутентификации должен иметь следующий интерфейс
+
+=over
+
+=item C<CTOR($SecData)>
+
+Создает пакет для авторизации на основе данных безопасности для пользователя
+
+=item C<< $obj->DoAuth($Challenge) >>
+
+Производит аутентификацию пользователя и инициализацию сессии, возвращает результат аутентификации, в виде массива ($status,$challenge).
+
+=item C<< $obj->ValidateSession($Challenge) >>
+
+Производит аутентификацию сессии, возвращает результат аутентификации, в виде массива ($status,$challenge).
+
 =cut
\ No newline at end of file
--- a/Lib/IMPL/Security/Auth/AuthResult.pm	Mon Mar 01 17:25:36 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-package IMPL::Security::Auth::Result;
-use strict;
-
-use base qw(IMPL::Object);
-use IMPL::Class::Property;
-use IMPL::Class::Property::Direct;
-
-BEGIN {
-    public _direct property State => prop_get;
-    public _direct property ClientSecData => prop_get;
-    public _direct property AuthMod => prop_get;
-}
-
-
-1;
--- a/Lib/IMPL/Security/Auth/Simple.pm	Mon Mar 01 17:25:36 2010 +0300
+++ b/Lib/IMPL/Security/Auth/Simple.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -2,15 +2,38 @@
 
 use base qw(IMPL::Security::Auth);
 use Digest::MD5;
-import IMPL::Security::Auth qw(:Const);
+import IMPL::Security::Auth qw(:Const GenSSID);
+
+use IMPL::Class::Property;
+
+BEGIN {
+	private property _passwordImage => prop_all;
+	private property _sessionCookie => prop_all;
+}
+
+sub CTOR {
+	my ($this,$secData) = @_;
+	
+	$this->_passwordImage($secData);
+}
 
 sub DoAuth {
-	my ($this,$clientData,$serverData) = @_;
+	my ($this,$challenge) = @_;
 
-	if (Digest::MD5::md5_hex($clientData) eq $serverData) {
-		return SUCCESS;
+	if (Digest::MD5::md5_hex($challenge) eq $this->_passwordImage) {
+		return (SUCCESS,$this->_sessionCookie(GenSSID));
 	} elsee {
-		return FAIL;
+		return (FAIL,undef);
+	}
+}
+
+sub ValidateSession {
+	my ($this,$cookie) = @_;
+	
+	if ($cookie eq $this->_sessionCookie) {
+		return (SUCCESS,undef);
+	} else {
+		return (FAIL,undef);
 	}
 }
 
--- a/Lib/IMPL/Web/Application.pm	Mon Mar 01 17:25:36 2010 +0300
+++ b/Lib/IMPL/Web/Application.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -6,8 +6,7 @@
 use IMPL::Class::Property;
 
 BEGIN {
-    public property RequestFactory => prop_all;
-    public property ContextInitializers => prop_all;
+    public property handlerError => prop_all;
 }
 
 # custom factory
@@ -21,13 +20,15 @@
     my ($this) = @_;
     
     while (my $request = $this->fetch_request()) {
-        my $context = $this->prepare_context($request);
-        $context->invoke($request);
+        my $action = $this->prepare_action($request);
+        $action->invoke($request);
     }
 }
 
 1;
 
+__END__
+
 =pod
 
 =head1 SYNOPSIS
@@ -38,10 +39,17 @@
 =head1 DESCRIPTION
 
 Зкземпляр приложения содержит в себе глобальные настройки, реализует контроллер запросов,
+в качестве источника запросов используется CGI или иной совместимый модуль.
 
-Получая запрос из источника запросов, создает контекст выполнения запроса
-затем выполняет запрос в указанном контексте.
+Процесс обработки запроса состоит из следующих частей
 
-Контекст формируется сначала из запроса, а затем посредством набора инициализаторов
+1. Получение cgi запроса
+2. Вызов модуля для инициализации объекта действия
+3. Инициализация контекста выполнения 
+4. Выполнение запроса
+5. Преобразование полученных данных в тело ответа
+
+
+
 
 =cut
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Web/Application/Action.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -0,0 +1,66 @@
+package IMPL::Web::Application::Action;
+
+use base qw(IMPL::Object);
+
+use IMPL::Class::Property;
+
+BEGIN {
+	public property application => prop_get | owner_set;
+	public property request => prop_get | owner_set;
+	public property response => prop_get | owner_set;
+	public property code => prop_get | owner_set;
+	public property chainHandlers => prop_get | owner_set | prop_list;
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 DESCRIPTION
+
+Определяет порядок выполнения запроса, форматирует результат, инициализирует контекст.
+
+Объект создается обработчиком запросов, таким как C<IMPL::Web::Application::UriController>.
+При этом формируется цепочка обработчиков запроса, эта цапочка будет выполняться с последнего добавленного,
+причем каждый добавленный обработчик в качестве одного из параметров получает не только текущий запрос,
+но и предыдущий обработчик.
+
+Типичная цепочка может быть такой, в порядке добавления
+
+$objSecCallToMethod($target,$method)
+$AuthenticateMethod
+$TDocumentOut($file)
+
+что приведет к следующей последовательности
+
+Action->Invoke() {
+	TDocumentOut->Invoke($Action,$nextHandler) {
+		my $result = $nextHandler() {
+			$AuthenticateMethod($Action,$nextHandler) {
+				my $context = $Action->application->security->Authenticate($Action->request,$Action->response);
+				return $context->Impersonate($nextHandler) {
+					$objSecCallToMethod->Invoke($Action,undef) {
+						IMPL::Security->AccessCheck($target,$method);
+						return $target->$method();
+					}
+				}
+			}
+		}
+		$this->format($result,$Action->response->streamBody);
+	}		
+}
+
+или как альтернатива может быть еще
+
+$objSecCallToMethod($target,$method)
+$AuthenticateMethod
+$TransfromToSimpleData
+$JSONOut
+
+В данной цепочке также происходит вызов метода, но его результат потом преобразуется
+в простые структуры и передается JSON преобразователю. Таким образом модулю логики
+не требуется знать о выходном формате, всю работу проделают дополнительные фильтры.
+
+=cut
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Web/Response.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -0,0 +1,58 @@
+package IMPL::Web::Response;
+
+use base qw(IMPL::Object);
+
+require IMPL::Exception;
+
+use IMPL::Class::Property;
+use HTTP::Response;
+
+BEGIN {
+	public property request => prop_get; # cgi query
+	public property contentType => prop_all, { validator => \&_checkHeaderPrinted }; # String
+	public property buffered => prop_get; # Boolean
+	public property cookies => prop_all, { validator => \&_checkHeaderPrinted }; # Hash
+	public property streamBody => { get => \&getStreamBody }; # stream
+	
+	private property _streamBody => prop_all; # stream
+	private property _streamOut => prop_all; # stream
+	private property _isHeaderPrinted => prop_all; # Boolean 
+}
+
+sub _checkHeaderPrinted {
+	my ($this,$value) = @_;
+	
+	die new IMPL::InvalidOperationException() if $this->_isHeaderPrinted;
+}
+
+sub getStreamBody {
+	my ($this) = @_;
+	
+	return $this->_streamBody if $this->buffered;
+	
+	
+}
+
+sub _PrintHeader {
+	my ($this) = @_;
+	
+	unless ($this->_isHeaderPrinted) {
+		$this->_isHeaderPrinted(1);
+		
+		
+	}
+}
+
+sub Send {
+	
+}
+
+1;
+
+__END__
+
+=pod
+
+
+
+=cut
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Web/Security.pm	Tue Mar 02 20:12:02 2010 +0300
@@ -0,0 +1,29 @@
+package IMPL::Web::Security;
+
+1;
+
+__END__
+
+=pod
+
+=head1 DESCRIPTION
+
+Модуль для аутентификации и авторизации веб запроса.
+
+Получает запрос, вчленяет из него информацию для авторизации, производит авторизацию пользователя
+и создает контекст безопасности.
+
+При этом использует указанные модули аутентификации.
+
+Информацию для аутентификации модкль получает через соответствующие адаптеры.
+
+=item C<IMPL::Web::Security::Server>
+
+аутентифицирует пользователя на основе данных, предоставленных сервером
+
+=item C<IMPL::Web::Security::Embed>
+
+Аутентифицирует пользователя используя указанные модули, при этом получает данные
+из запроса.
+
+=cut
\ No newline at end of file