annotate lib/IMPL/Web/Handler/SecureCookie.pm @ 417:3ed0c58e9da3 ref20150831

working on di container, tests
author cin
date Mon, 02 Nov 2015 01:56:53 +0300
parents c6e90e02dd17
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
407
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
1 package IMPL::Web::Handler::SecureCookie;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
2 use strict;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
3
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
4
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
5 use Digest::MD5 qw(md5_hex);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
6 use IMPL::Const qw(:prop);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
7 use IMPL::Security::Auth qw(:Const GenSSID);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
8 use IMPL::declare {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
9 require => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
10 SecurityContext => 'IMPL::Security::Context',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
11 User => 'IMPL::Security::Principal',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
12 AuthSimple => 'IMPL::Security::Auth::Simple',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
13 Exception => 'IMPL::Exception',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
14 OperationException => '-IMPL::InvalidOperationException',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
15 HttpResponse => '-IMPL::Web::HttpResponse'
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
16 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
17 base => {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
18 'IMPL::Object' => undef,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
19 'IMPL::Object::Autofill' => '@_',
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
20 'IMPL::Object::Serializable' => undef
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
21 },
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
22 props => [
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
23 salt => PROP_RO,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
24 _security => PROP_RW,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
25 _cookies => PROP_RW
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
26 ]
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
27 };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
28
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
29 sub CTOR {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
30 my ($this) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
31
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
32 $this->salt('DeadBeef') unless $this->salt;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
33 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
34
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
35 sub ValidateCookie {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
36 my ($this,$sid,$cookie,$sign) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
37
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
38 return 1 if $sid and $cookie and $sign and $sign eq md5_hex($this->salt,$sid,$cookie,$this->salt);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
39
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
40 return 0;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
41 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
42
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
43 sub AuthCookie {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
44 my ($this,$sid,$cookie,$sign, $context) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
45
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
46 if (eval { $context->auth->isa(AuthSimple) }) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
47 my ($result,$challenge) = $context->auth->DoAuth($cookie);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
48 return $result;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
49 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
50
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
51 return AUTH_FAIL;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
52 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
53
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
54 sub Invoke {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
55 my ($this,$action,$nextHandler) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
56
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
57 return unless $nextHandler;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
58
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
59 my $context;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
60 $this->_security($action->security);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
61
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
62
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
63 my $sid = $action->cookie('sid',qr/(\w+)/);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
64 my $cookie = $action->cookie('sdata',qr/(\w+)/);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
65 my $sign = $action->cookie('sign',qw/(\w+)/);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
66
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
67 if ( $this->ValidateCookie($sid,$cookie,$sign) ) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
68 # TODO: add a DeferredProxy to deffer a request to a data source
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
69 if ( $context = $this->_security->sessions->GetById($sid) ) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
70 if ( eval { $context->auth->isa(AuthSimple) } ) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
71 my ($result,$challenge) = $context->auth->DoAuth($cookie);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
72
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
73 $context->authority($this);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
74
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
75 if ($result == AUTH_FAIL) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
76 $context = undef;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
77 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
78 } else {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
79 undef $context;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
80 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
81 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
82
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
83 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
84
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
85 $context ||= SecurityContext->new(principal => User->nobody, authority => $this);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
86
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
87 my $httpResponse = eval { $context->Impersonate($nextHandler,$action); };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
88 my $e = $@;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
89
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
90 die $e if $e;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
91
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
92 die OperationException->new("A HttpResponse instance is expected")
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
93 unless ref $httpResponse && eval { $httpResponse->isa(HttpResponse) };
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
94
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
95 return $this->_WriteResponse($httpResponse);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
96 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
97
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
98 sub InitSession {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
99 my ($this,$user,$roles,$auth,$challenge) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
100
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
101 my ($status,$answer);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
102
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
103 if ($auth) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
104 ($status,$answer) = $auth->DoAuth($challenge);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
105 } else {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
106 $status = AUTH_SUCCESS;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
107 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
108
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
109 die OperationException->new("This provider doesn't support multiround auth")
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
110 if ($status == AUTH_INCOMPLETE || $answer);
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
111
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
112 if ($status == AUTH_SUCCESS) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
113 my $sid = GenSSID();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
114 my $cookie = GenSSID();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
115
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
116 $this->_cookies({
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
117 sid => $sid,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
118 sdata => $cookie
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
119 });
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
120
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
121 my $context = $this->_security->sessions->Create({
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
122 sessionId => $sid,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
123 principal => $user,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
124 auth => AuthSimple->Create(password => $cookie),
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
125 authority => $this,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
126 rolesAssigned => $roles
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
127 });
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
128
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
129 $context->Apply();
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
130
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
131 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
132
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
133 return $status;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
134 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
135
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
136 sub CloseSession {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
137 my ($this) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
138 if(my $session = SecurityContext->current) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
139 $this->_cookies({
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
140 sid => undef,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
141 sdata => undef
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
142 })
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
143 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
144 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
145
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
146 sub _WriteResponse {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
147 my ($this,$response) = @_;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
148
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
149 if (my $data = $this->_cookies) {
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
150
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
151 my $sign = $data->{sid} && md5_hex(
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
152 $this->salt,
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
153 $data->{sid},
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
154 $data->{sdata},
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
155 $this->salt
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
156 );
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
157
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
158 $response->cookies->{sid} = $data->{sid};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
159 $response->cookies->{sdata} = $data->{sdata};
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
160 $response->cookies->{sign} = $sign;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
161 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
162
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
163 return $response;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
164 }
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
165
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
166 1;
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
167
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
168 __END__
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
169
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
170 =pod
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
171
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
172 =head1 NAME
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
173
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
174 C<IMPL::Web::Handler::SecureCookie>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
175
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
176 =head1 DESCRIPTION
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
177
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
178 Возобновляет сессию пользователя на основе информации переданной через Cookie.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
179
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
180 Использует механизм подписи информации для проверки верности входных данных перед
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
181 началом каких-либо действий.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
182
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
183 Данный обработчик возвращает результат выполнения следдующего обработчика.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
184
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
185
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
186
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
187 =head1 MEMBERS
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
188
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
189 =head2 C<[get,set] salt>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
190
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
191 Скаляр, использующийся для подписи данных.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
192
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
193
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
194 =head2 C<InitSession($user,$roles,$auth,$challenge)>
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
195
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
196 Инициирует сессию, поскольку данный модуль отвечает за взаимодействие с клиентом
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
197 при проверки аутентификации, ему передаются данные аутентификации для
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
198 продолжения обмена данными с клиентом. Если создается новая сессия, по
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
199 инициативе веб-приложения, то C<$auth> должно быть пусто.
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
200
c6e90e02dd17 renamed Lib->lib
cin
parents:
diff changeset
201 =cut