8 Einträge, 1 Seite |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<html>
<head>
<title>Sessions für Shopsystem</title>
<style type="text/css">
td{ border: 1pt outset #EEEEEE; background-color: white}
th{ background-color: ghostwhite; }
h1.sub-title { font-size: 16pt; }
</style>
</head>
<body bgcolor="#EEEEEE">
<h1>Sessions im Request für Shopsysteme</h1>
<h1 class="sub-title">Sessions ohne Speicherung der Session-Daten (Cookies, Files, DB)</h1>
<li>Das System
<li>Vorteile - Nachteile
<li>Codebeispiel für nicht-cookiebasierte Sessions
<li>Original-Perlunity-Thread (kopiert, damit Quelle nicht verloren geht)
<hr />
<h2>Das System</h2>
<li>Cookies
<p>Man geht davon aus, dass keine Cookies beim User möglich sind. ( Wenn das Gegenteil bewiesen ist, übergibt man die SID doch besser in einem Cookie und nicht im Request )</p>
<li>Verfallsdatum
<p>Die Session-ID braucht dringend ein Verfallsdatum. (z.B. 6 Stunden) (Bspl.: Die Kunden eines Shopsystems verlinken einzelne Produktseiten, samt ihrer ID...) Wenn eine ID verfallen ist vergibt man stillschweigend eine neue. Wenn eine falsche ID eingegeben wurde ( mit ner Regex das Schema prüfen ) vergibt man stillschweigend eine neue.</p>
<li>Kontra Abspeichern der Session
<p>Auf keinen Fall, macht man für jede Session einen Datenbankeintrag. Diese Einträge braucht man erst, wenn der Warenkorb befüllt wird.</p>
<li>Der Warenkorb
<p>Warenkörbe haben einen extra Platz in so einer ID. Dieser Teil ist, wenn der Warenkorb befüllt wurde, immer gleich. Eigentlich ist das eine zweite ID innnerhalb der Session. Dieser Teil hat ein längeres Haltbarkeitsdatum (12 Wochen), wird aber, bei einer abgelaufenen Sid, nur akzeptiert, wenn er aus einen Cookie kommt.</p>
<li>Suchmaschinen und Spider
<p>Auf Suchmaschinen (Spider) muß man achten. Wenn die sich in so einen Shop verbeissen und Dank der ewig neuen Sid's, ewig neue Seiten finden kann das unschön enden. (Ich würde hier KFSW::SpiderDetect empfehlen, wenn ich es schon veröffentlicht hätte. SCNR) Ein erkannter Spider bekommt eine fixe ID, z.B. my_shop_name, dann findet er jede mögliche Seite nur einmal und gut ist. Da die Id nicht dem normalen Schema entspricht wird sie bei einem normalen User-Request ersetzt. (s.o) Dabei gibt es entweder eine neue ID oder, wenn der User schon einen Cookie haben sollte, die ID aus dem Cookie.</p>
<li>Sicherheit
<p>Alles Sicherheitsdenken, Kontrollierwünsche etc scheitern an der zu hohen Systemlast. Plane die Sids ohne irgendwelche sicherheitsrelevanten Features. (Für den Adminbereich mußt du natürlich was anderes machen.)</p>
<li>Beispiel Sid:
<pre>
perl -e '$sid = time() . "XY" . rand(1) . "ZZ" . time() . "XY" . rand(1) . "ZZ" . time();
$sid =~ s/\./PT/g;
print"$sid\n"'
Ausgabe:
1050269667XY0PT917397911734046ZZ1050269667XY0PT0304125736906542ZZ1050269677
</pre>
<p>Wenn du das jetzt immer an ZZ zerlegst hast du drei Teile. Warenkorb, eigentliche Sid und Cachebrecher. Jeder Teil hat sein eigenes Startdatum.</p>
<p>Beim nächsten Aufruf wäre die Sid z.B.<p>
<pre>
1050269667XY0PT917397911734046ZZ1050269667XY0PT0304125736906542ZZ1050269700
</pre>
<p>Dieser String wird jetzt wie folgt geprüft: Erstmal eine RegEx drüber ob das Ding passen kann. Wenn das OK ist, geht es weiter:</p>
<p>Codebeispiel:</p>
<pre>
sub validate_session{
# ---- usage
# if( validate_session( $sessionDataToValidate ) ){ print "Session Ok!\n"; }
# requires: constant SESSION_TIME = 123; #ms
# ----
# prüfen, ob gültige sid: a)muster b)haltbarkeit
my $session = $_[0];
my $return = 0;
if( $session =~ /\d{10}XY\d*PT\d{10}/
and (split /XY/, $session)[0] > time() - SESSION_TIME ){
$return = 1;
}
return $return;
}
# --------------------------------------------------------
</pre>
<p>a.) Wenn die Sid aus einem Cookie kommt, bleibt der erste Teil für z.B. sieben Wochen gültig.
Der zweite Teil wird nach z.B. 6 Stunden erneuert.
Der dritte Teil wird bei jedem Request durch time() ersetzt.</p>
<p>b.) Wenn die Sid nicht aus einem Cookie kommt, gibt es nach 6 Stunden eine komplett neue Sid.
Der dritte Teil wird bei jedem Request durch time() ersetzt.</p>
<li>Warum dieses System?
Damit funktionieren Warenkörbe zwar nur mit Cookie richtig gut, aber ein Kunde, der in den Shop kommt und keine Cookies hat, kann dort in Ruhe einkaufen. (Er muß natürlich in 6 Stunden durch sein) Anders geht es leider nicht, denn wenn man die Warenkorbinformation aus dem Query-String länger als X Stunden akzeptiert, hat man wieder das Problem mit den Kunden, die Shopseiten verlinken und Ihre Sid im Link lassen. Gleiches gilt für versehentlich nicht erkannte WebSpider.
<hr />
<h2>Vorteile - Nachteile</h2>
<h3>Vorteile</h3>
<li>Es werden keine unnötigen Daten gespeichert
<li>Funktioniert auch ohne Cookies (die jeder Benutzer deaktivieren kann)
<li>
<h3>Nachteile</h3>
<li>Wenn der Benutzer keine Cookies annimmt kann er nur für einen begrenzten Zeitraum einkaufen
<li>Spider raffen die Session nicht und finden so immer neue Seiten)
<li>st nicht sicher genug - die Session ist immer einen bestimmten Zeitraum gültig. Kommt jemand anderes an die Session ran kann er sie ausnutzen
<hr />
<h2>Codebeispiel für nicht-cookiebasierte Sessions</h2>
<pre>
<!--c1--><table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td><b>Code</b> </td></tr><tr><td id="CODE"><!--ec1--><br>...<br>use constant SESSION_TIME =&> &'60000&'; #ms<br>...<br># ---- CGI<br>my &$cgi = CGI-&>new&(&);<br>my &$query = &$cgi-&>Vars&(&);<br># ---- SETTINGS<br>my %subs = &(&);<br>&$subs{relative_url} = &$cgi-&>url&(-relative=&>1&);<br>&$subs{full_url} = &$cgi-&>url&(-full=&>1&);<br>...<br>print &$cgi-&>header&(-charset=&>&'ISO-8859-1&',<br> -expires=&>&'+1s&',<br> -type=&>&'text/html&',<br> &);<br><br>if&( &(exists &$query-&>{sid}&) # wenn session existiert<br>and validate_session&( &$query-&>{sid} &) &){ # und gültig ist<br> #session verlängern<br> &$query-&>{sid} = time&(&) . &"XY&" . &(split /XY/, &$query-&>{sid}&)&[1&];<br> #settings<br> &$subs{self} = &$subs{relative_url} . &'?sid=&' . &$query-&>{sid} . &'&file=&' . &$query-&>{file};<br> &$subs{query} = &'?sid=&' . &$query-&>{sid} . &'&file=&' . &$query-&>{file};<br> &$subs{domain} = &"http&://&" . DOMAIN;<br> &$subs{sid} = &$query-&>{sid};<br> &$subs{file} = &$query-&>{file};<br>...<br>}else{ #wenn keine session existiert / session nicht gültig ist<br> if&( exists &$query-&>{action}<br> and &$query-&>{action} eq &"login&"<br> and main&:&:validate_login&(&$query-&>{usn}, &$query-&>{pwd}&) &){<br> &$query-&>{sid} = time&(&) . &"XY&" . rand&(1&);<br> &$query-&>{sid} =~ s/&\./PT/g;<br> #settings<br> &$subs{self} = &$subs{relative_url} . &'?sid=&' . &$query-&>{sid} . &'&file=&' . &$query-&>{file};<br> &$subs{query} = &'?sid=&' . &$query-&>{sid} . &'&file=&' . &$query-&>{file};<br> &$subs{domain} = &"http&://&" . DOMAIN;<br> # erstes einloggen =&> INDEX<br> print qq~&<h1&>Login korrekt&!&</h1&>~;<br> print qq~&<p&>&<a href=&"&$subs{self}&"&>weiter &gt;&gt;&gt;&</a&>&</p&>~;<br> print qq~&<p&>SID&: &$query-&>{sid}&</p&>~;<br> print qq~&<p&>file&: &$query-&>{file}&</p&>~;<br> }else{<br> print &$loginForm;<br> }<br>}<br>exit&( 1 &);<br>...<br># --------------------------------------------------------<br># SUBS<br># --------------------------------------------------------<br>sub validate_login{<br># ---- usage<br># if&( validate_login&( &$query-&>{usn}, &$query-&>{pwd} &) &){ print &"Login ok&!&\n&"; }<br># ---- requirements<br># modul&: Crypt&:&:PasswdMD5<br># &$passfile -&> File mit USN&|PWD&(cryptedBy&: Crypt&:&:PasswdMD5&)&\n<br> my &(&$usn, &$pwd&) = @_;<br> my &$return = 0;<br> open&(DAT, &$passfile&) &|&| die &"&$&! &(&$passfile&)&";<br> flock DAT, 1 if UNIX;<br> my @passfile = &<DAT&>;<br> close&(DAT&);<br> foreach &( @passfile &){<br> chomp &$_;<br> if&( &$usn eq &(split /&\&|/,&$_&)&[0&] &){<br> if &(unix_md5_crypt&(&$pwd, &(split /&\&|/,&$_&)&[1&]&)<br> eq &(split /&\&|/,&$_&)&[1&] &) {<br> # Passwort in Ordnung<br> &$return = 1;<br> }else{<br> &$return = 0;<br> }<br> }else{<br> &$return = 0;<br> }<br> }<br> return &$return;<br>}<br># --------------------------------------------------------<br>sub validate_session{<br># ---- usage<br># if&( validate_session&( &$sessionDataToValidate &) &){ print &"Session Ok&!&\n&"; }<br># ----<br># prüfen, ob gültige sid&: a&)muster b&)haltbarkeit<br> my &$session = &$_&[0&];<br> my &$return = 0;<br> if&( &$session =~ /&\d{10}XY&\d*PT&\d{10}/<br> and &(split /XY/, &$session&)&[0&] &> time&(&) - SESSION_TIME &){<br> &$return = 1;<br> }<br> return &$return;<br>}<br># --------------------------------------------------------<br><!--c2--></td></tr></table><!--ec2-->
</pre>
<hr />
<h2>Original-Perlunity-Thread (kopiert, damit Quelle nicht verloren geht)</h2>
<table>
<tr>
<th>Sessions für Shopsysteme</th>
</tr>
<td>Quelle: Threat auf <a href="http://www.perlunity.de">perlunity.de</a></td>
</tr>
<tr>
<td>
<p>
Hi!<br />
Will mir gerade ein Session-Management-Teil stricken.
Dazu wollte ich den User über die IP identifizieren
(mehr dazu siehe weiter unten).
Bei AOL-Usern ist das aber etwas doof, weil die ja jedesmal eine
andere IP haben (weis nicht mehr genau wieso, war glaube ich wegen anonymen
Proxy oder so - egal).
Trifft das noch auf andere User-Gruppen zu?
</p>
<p class="b"> Zurück zur Frage, wo steht nochmal drin, ob der User AOL oder sonstwas benutzt?</p>
<p>
Dann noch was zum Session-Teil.
Hatte eigentlich vor, auf Kekse soweit es geht zu verzichten.
Jetzt steht allerdings Leistungsfähigkeit & Sicherheit gegen Kekse.
Wieso sollte man nochmal auf den Einsatz von Keksen verzichten?
(außer, dass manche Leute Kekse aus verständlichen Gründen deaktivieren)
Was würdet ihr machen?</p>
<p>--> Kurze Anmerkung, wie ich mir das vorstelle (in schmuckem pseudo-perl):</p>
<pre>
if( AOL-User ){
Keks mit SessionID setzen
Eintrag in Session-DB, mit SessionID & "AOL"
}else{
Eintrag in Session-DB mit SessionID & IP
#optional: Keks setzen
}
</pre>
<p>mfg pktm</p>
</td></tr><tr><td>
<p>
Hallo!<br />
Die IP ist generell keine gute Idee. Nebst AOL benutzen viele Provider Proxis,
ob für den Kunden sichtbar oder nicht. Wenn du uns sagst, wofür du die Session
brauchst und warum du keines der vorhandenen Module nutzen willst,
ist es einfacher dir etwas zu raten.
Ich mache je nach Bedarf mal Sessions mit Cookies oder im Querystring,
mit TimeOut oder ohne, bei Cookies aber geneerell mit Fallback, für den Fall,
daß der User keine Kekse will. Es kommt auf den Anwendungsbereich an.
Ganz am Anfang habe ich mal, im Shop, für jeden Sch.... ne Session angelegt mit
Kontrollfunktion etc.
Ab 1000 Dateien pro Tag wird man da ruhiger;-)</p>
<p>Gruß<br />
Kristian</p>
</td></tr><tr><td>
<p>
Das mit den 1000 Dateien kann ich glaube ich verstehen.
Die Session wollte ich in mein Shopsystem einbauen.
Einmal für den Admin-Bereich und einmal für den Warenkorb.
Das mit AOL ist irgendwie was spezielles, weil die Leute jedesmal über eine
anderen Proxy geschickt werden,
mehr dazu gabs mal hier:</p>
<a href="http://perl.black-cube.net/bin/ultraboard/UltraBoard.cgi?action=Read&BID=13&TID=20114&P=1&SID=99#ID24" target="_blank">
http://perl.black-cube.net/bin/ultraboard/UltraBoard.cgi?action=Read&BID=13&TID=20114&P=1&SID=99#ID24</a>
<p>aber der Link geht nicht mehr;-(</p>
<p>Mit den anderen Proxys hab ich eigentlich doch kein Problem, bleibt doch immer
der selbe - oder?</p>
<p>Dann gibts da ja noch die Möglichkeit mit mod_rewrite, den hab ich aber bei
meinem Provider nicht.</p>
<p>Hm, also - Vorschläge? :-)<br />
mfg pktm</p>
</td></tr><tr><td>
<p>
Hallo!<br />
Vergiß die AOL-User und überdenke dein Session-Konzept.
In einem Shop würde ich es so machen:</p>
<p>Erstmal geht man davon aus, daß keine Cookies beim User möglich sind.
( Wenn das Gegenteil bewiesen ist, übergibt man die SID in einem Cookie und
nicht im Request )</p>
<p>Die Session-ID braucht dringend ein Verfallsdatum. (z.B. 6 Stunden)
(Die Kunden verlinken einzelne Produktseiten, samt ihrer ID...)
Wenn eine ID verfallen ist vergibt man stillschweigend eine neue.
Wenn eine falsche ID eingegeben wurde ( mit ner Regex das Schema prüfen )
vergibt man stillschweigend eine neue.</p>
<p>In der Session-ID "bricht" man, bei Bedarf, den Browsercache, indem man time()
mit einbaut.</p>
<p>Auf keinen Fall, macht man für jede Session einen Datenbankeintrag. Diese
Einträge braucht man erst,
wenn der Warenkorb befüllt wird.</p>
<p>Warenkörbe haben einen extra Platz in so einer ID. Dieser Teil ist, wenn der
Warenkorb befüllt wurde, immer gleich. Eigentlich ist das eine zweite ID
innnerhalb der Session. Dieser Teil hat ein längeres Haltbarkeitsdatum
(12 Wochen), wird aber, bei einer abgelaufenen Sid, nur akzeptiert, wenn er aus
einen Cookie kommt.</p>
<p>Auf Suchmaschinen (Spider) muß man achten. Wenn die sich in so einen Shop
verbeissen und Dank der ewig neuen Sid's, ewig neue Seiten finden kann das
unschön enden. (Ich würde hier KFSW::SpiderDetect empfehlen, wenn ich es schon
veröffentlicht hätte. SCNR)
Ein erkannter Spider bekommt eine fixe ID, z.B. my_shop_name, dann findet er
jede mögliche Seite nur einmal und gut ist. Da die Id nicht dem normalen Schema
entspricht wird sie bei einem normalen User-Request ersetzt. (s.o)
Dabei gibt es entweder eine neue ID oder, wenn der User schon einen Cookie
haben sollte, die ID aus dem Cookie.</p>
<p>Alles Sicherheitsdenken, Kontrollierwünsche etc scheitern an der zu hohen
Systemlast. Plane die Sids ohne irgendwelche sicherheitsrelevanten Features.
(Für den Adminbereich mußt du natürlich was anderes machen.)</p>
<p>So, da hast du ein paar Anregungen, die auf drei Jahren (Shopbetrieb)Erfahrung
beruhen, ich hoffe sie helfen dir.</p>
<p>Gruß<br />
Kristian</p>
</td></tr><tr><td>
<p>
Hi!<br />
Das Konzept leuchtet ein´:
* Cookie immer setzen, wenn möglich
* SID in request mitgeben
Nur das mit dem Warenkorb hab ich nicht so ganz verstanden.
Die SID besteht aus 2 Teilen.<br />
1. Teil: localtime + 6h, irgendwie verdreht<br />
2. Teil: ? Warenkorb ?<br />
Einfach eine zufallsgenerierte ID nehmen?
Geht der Teil denn nicht verkoren, wenn ich stillschweigend eine neue ID
vergebe?</p>
<p>mfg pktm</p>
</td></tr><tr><td>
<p>
Hallo<br />
> Das Konzept leuchtet ein´:<br />
> * Cookie immer setzen, wenn möglich<br />
> * SID in request mitgeben<br />
Hmm, nein, da habe ich gefaselt, einen Cookie gibt es nur, wenn er was in den
Warenkorb legt.</p>
<p>Beispiel Sid:</p>
<pre>
perl -e '$sid = time() . "XY" . rand(1) . "ZZ" . time() . "XY" . rand(1) . "ZZ" . time();
$sid =~ s/\./PT/g;
print"$sid\n"'
Ausgabe:
1050269667XY0PT917397911734046ZZ1050269667XY0PT0304125736906542ZZ1050269677
</pre>
<p>Wenn du das jetzt immer an ZZ zerlegst hast du drei Teile.
Warenkorb, eigentliche Sid und Cachebrecher.
Jeder Teil hat sein eigenes Startdatum.</p>
<p>Beim nächsten Aufruf wäre die Sid z.B.</p>
<pre>
1050269667XY0PT917397911734046ZZ1050269667XY0PT0304125736906542ZZ1050269700
</pre>
<p>Dieser String wird jetzt wie folgt geprüft:
Erstmal ne regex drüber ob das Ding passen kann.
Wenn das OK ist, geht es weiter:</p>
<p>a.) Wenn die Sid aus einem Cookie kommt, bleibt der erste Teil für z.B. sieben
Wochen gültig.<br />
Der zweite Teil wird nach z.B. 6 Stunden erneuert.<br />
Der dritte Teil wird bei jedem Request durch time() ersetzt.</p>
<p>b.) Wenn die Sid nicht aus einem Cookie kommt, gibt es nach 6 Stunden eine
komplett neue Sid.<br />
Der dritte Teil wird bei jedem Request durch time() ersetzt.</p>
<p>Damit funktionieren Warenkörbe zwar nur mit Cookie richtig gut, aber ein Kunde,
der in den Shop kommt und keine Cookies hat, kann dort in Ruhe einkaufen.
(Er muß natürlich in 6 Stunden durch sein)
Anders geht es leider nicht, denn wenn man die Warenkorbinformation aus dem
Query-String länger als X Stunden akzeptiert, hat man wieder das Problem mit
den Kunden, die Shopseiten verlinken und Ihre Sid im Link lassen.
Gleiches gilt für versehentlich nicht erkannte WebSpider.</p>
<p>Sind damit alle Klarheiten restlos beseitigt?;-)</p>
<p>Gruß Kristian</p>
<p>PS: 6 Stunden / 7 Wochen kann man natürlich durch andere Werte ersetzen</p>
</td></tr><tr><td>
<p>
Hi,<br />
denke mal, dass bei AOL für die IP auch ein hostname mit "AOL" existiert.
So wie bei t-online oder netcologne:</p>
<pre>
>>dial-213-168-xx-xxx.netcologne.de<<
</pre>
<p>so kommst du an den hostnamen ran:</p>
<pre>
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Host-Ausgabe der REMOTE-Adresse</title></head><body><pre>\n";
use Socket;
my $remote=$ENV{'REMOTE_ADDR'};
my $addr = inet_aton($remote);
my $Wert = gethostbyaddr($addr, AF_INET);
print "$Wert\n";
print "</pre></body></html>\n";
</pre>
<p>gruß klaus</p>
</td></tr><tr><td>
<p>Ende</p>
</td></tr>
</table>
<hr />
</body>
</html>
8 Einträge, 1 Seite |