File Coverage

blib/lib/CGI/Session/Auth.pm
Criterion Covered Total %
statement 44 118 37.2
branch 9 30 30.0
condition 3 14 21.4
subroutine 11 26 42.3
pod 8 10 80.0
total 75 198 37.8


line stmt bran cond sub pod time code
1             ###########################################################
2             # CGI::Session::Auth
3             # Authenticated sessions for CGI scripts
4             ###########################################################
5             #
6             # $Id: Auth.pm 32 2007-09-02 13:04:22Z geewiz $
7             #
8              
9             package CGI::Session::Auth;
10 2     2   72760 use base qw(Exporter);
  2         6  
  2         332  
11              
12 2     2   50 use 5.008;
  2         6  
  2         100  
13 2     2   11 use strict;
  2         10  
  2         61  
14 2     2   10 use warnings;
  2         10  
  2         79  
15 2     2   11 use Carp;
  2         8  
  2         182  
16 2     2   13 use Digest::MD5 qw( md5_hex );
  2         5  
  2         3358  
17              
18             our %EXPORT_TAGS = ( 'all' => [ qw(
19             ) ] );
20             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
21             our @EXPORT = qw(
22             );
23              
24             our $VERSION = do { q$Revision: 32 $ =~ /Revision: (\d+)/; sprintf "1.%03d", $1; };
25              
26             ###########################################################
27             ###
28             ### general methods
29             ###
30             ###########################################################
31              
32             ###########################################################
33              
34             sub new {
35            
36             ##
37             ## class constructor
38             ## see POD below
39             ##
40            
41 3     3 1 87091 my $class = shift;
42 3         10 my ($params) = @_;
43            
44 3 50       17 $class = ref($class) if ref($class);
45             # check required params
46 3         17 my %classParams = (
47             Session => ['CGI::Session'],
48             CGI => ['CGI', 'CGI::Simple'],
49             );
50 3         15 foreach my $classParam (keys %classParams) {
51 6 50       20 croak "Missing $classParam parameter" unless exists $params->{$classParam};
52 0         0 croak "$classParam parameter is not a " . join(' or ', @{$classParams{$classParam}}) . " object"
  9         91  
53 6 50       9 unless grep { $params->{$classParam}->isa($_) } @{$classParams{$classParam}};
  6         16  
54             }
55            
56 3   50     247 my $self = {
      50        
      50        
57            
58             #
59             # general parameters
60             #
61            
62             # parameter "Session": CGI::Session object
63             session => $params->{Session},
64             # parameter "CGI": CGI object
65             cgi => $params->{CGI},
66             # parameter "LoginVarPrefix": prefix of login form variables (default: 'log_')
67             lvprefix => $params->{LoginVarPrefix} || 'log_',
68             # parameter "IPAuth": enable IP address based authentication (default: 0)
69             ipauth => $params->{IPAuth} || 0,
70             # parameter "Log": enable logging (default: 0)
71             log => $params->{Log} || 0,
72              
73             #
74             # class members
75             #
76            
77             # the current URL
78             url => $params->{CGI}->url,
79             # logged-in status
80             logged_in => 0,
81             # user id
82             userid => '',
83             # user profile data
84             profile => {},
85             # Log::Log4perl logger, see "log" above
86             logger => undef,
87             };
88            
89 3         11079 bless $self, $class;
90            
91 3 50       29 if ( $self->{log}) {
92 0         0 require Log::Log4perl;
93 0         0 $self->{logger} = Log::Log4perl->get_logger($class);
94 0         0 $self->_debug("logging enabled");
95             }
96              
97 3         24 return $self;
98             }
99              
100             ###########################################################
101              
102             sub authenticate {
103              
104             ##
105             ## authenticate current visitor
106             ##
107            
108 0     0 1 0 my $self = shift;
109            
110             # is this already a session by an authorized user?
111 0 0       0 if ( $self->_session->param("~logged-in") ) {
112 0         0 $self->_debug("User is already logged in in this session");
113             # set flag
114 0         0 $self->_loggedIn(1);
115             # load user profile
116 0         0 my $userid = $self->_session->param('~userid');
117 0         0 $self->_loadProfile($userid);
118 0         0 return 1;
119             }
120             else {
121 0         0 $self->_debug("User is not logged in in this session");
122             # reset flag
123 0         0 $self->_loggedIn(0);
124             }
125            
126             # maybe someone's trying to log in?
127 0         0 my $lg_name = $self->_cgi->param( $self->{lvprefix} . "username" );
128 0         0 my $lg_pass = $self->_cgi->param( $self->{lvprefix} . "password" );
129            
130 0 0 0     0 if ($lg_name && $lg_pass) {
131             # Yes! Login data coming in.
132 0         0 $self->_debug("User trying to log in");
133 0 0       0 if ($self->_login( $lg_name, $lg_pass )) {
134 0         0 $self->_debug("login successful, userid: ", $self->{userid});
135 0         0 $self->_loggedIn(1);
136 0         0 $self->_session->param("~userid", $self->{userid});
137 0         0 $self->_session->clear(["~login-trials"]);
138 0         0 return 1;
139             }
140             else {
141             # the login seems to have failed :-(
142 0         0 $self->_debug("Login failed");
143 0   0     0 my $trials = $self->_session->param("~login-trials") || 0;
144 0         0 return $self->_session->param("~login-trials", ++$trials);
145             }
146             }
147            
148             # or maybe we can authenticate the visitor by his IP address?
149 0 0       0 if ($self->{ipauth}) {
150             # we may check the IP
151 0 0       0 if ($self->_ipAuth()) {
152 0         0 $self->_debug("IP authentication successful, userid: ", $self->{userid});
153 0         0 $self->_loggedIn(1);
154 0         0 $self->_session->param("~userid", $self->{userid});
155 0         0 $self->_session->clear(["~login-trials"]);
156 0         0 return 1;
157             }
158             }
159            
160             }
161              
162             ###########################################################
163              
164             sub sessionCookie {
165            
166             ##
167             ## make cookie with session id
168             ##
169            
170 0     0 1 0 my $self = shift;
171            
172 0         0 my $cookie = $self->_cgi->cookie($self->_session->name() => $self->_session->id );
173 0         0 return $cookie;
174             }
175              
176             ###########################################################
177              
178             sub loggedIn {
179            
180             ##
181             ## get internal logged-in flag
182             ##
183            
184 2     2 1 9 my $self = shift;
185            
186 2         10 return $self->_loggedIn;
187             }
188              
189             ###########################################################
190              
191             sub profile {
192            
193             ##
194             ## accessor to user profile fields
195             ##
196            
197 0     0 1 0 my $self = shift;
198 0         0 my $key = shift;
199            
200 0 0       0 if (@_) {
201 0         0 my $value = shift;
202 0         0 $self->{profile}{$key} = $value;
203 0         0 $self->_debug("set profile field '$key' to '$value'");
204             }
205            
206 0         0 return $self->{profile}{$key};
207             }
208              
209             ###########################################################
210              
211             sub hasUsername {
212            
213             ##
214             ## check for given user name
215             ##
216            
217 0     0 1 0 my $self = shift;
218 0         0 my ($username) = @_;
219            
220 0         0 return ($self->{profile}{username} eq $username);
221             }
222              
223             ###########################################################
224              
225             sub logout {
226            
227             ##
228             ## revoke users logged-in status
229             ##
230            
231 0     0 1 0 my $self = shift;
232            
233 0         0 $self->_loggedIn(0);
234 0         0 $self->_info("User '", $self->{profile}{username}, "' logged out");
235             }
236              
237             ###########################################################
238              
239             sub uniqueUserID {
240            
241             ##
242             ## generate a unique 32-character user ID
243             ##
244            
245 0     0 0 0 my ($username) = @_;
246            
247 0         0 return md5_hex(localtime, $username);
248             }
249              
250             ###########################################################
251             ###
252             ### backend specific methods
253             ###
254             ###########################################################
255              
256             ###########################################################
257              
258             sub _login {
259            
260             ##
261             ## check login credentials and load user profile
262             ##
263            
264 0     0   0 my $self = shift;
265 0         0 my ($username, $password) = @_;
266            
267             # allow only the guest user, for real applications use a subclass
268 0 0 0     0 if ( ($username eq 'guest') && ( $password eq 'guest' ) ) {
269 0         0 $self->_info("User '$username' logged in");
270 0         0 $self->{userid} = "guest";
271 0         0 $self->_loadProfile($self->{userid});
272 0         0 return 1;
273             }
274            
275 0         0 return 0;
276             }
277              
278             ###########################################################
279              
280             sub _ipAuth {
281            
282             ##
283             ## authenticate by the visitors IP address
284             ##
285            
286 0     0   0 return 0;
287             }
288              
289             ###########################################################
290              
291             sub _loadProfile {
292            
293             ##
294             ## load the user profile for a given user id
295             ##
296            
297 0     0   0 my $self = shift;
298 0         0 my ($userid) = @_;
299            
300             # store some dummy values
301 0         0 $self->{userid} = $userid;
302 0         0 $self->{profile}{username} = 'guest';
303             }
304              
305             ###########################################################
306              
307 0     0 0 0 sub saveProfile {
308              
309             ##
310             ## save probably modified user profile
311             ##
312              
313             }
314              
315             ###########################################################
316              
317             sub isGroupMember {
318            
319             ##
320             ## check if user is in given group
321             ##
322            
323             # abstract class w/o group functions, for real applications use a subclass
324 0     0 1 0 return 0;
325             }
326              
327             ###########################################################
328             ###
329             ### internal methods
330             ###
331             ###########################################################
332              
333             ###########################################################
334              
335             sub _debug {
336            
337             ##
338             ## log debug message
339             ##
340            
341 2     2   4 my $self = shift;
342            
343 2 50       9 $self->{logger}->debug(@_) if $self->{logger};
344             }
345              
346             ###########################################################
347              
348             sub _info {
349            
350             ##
351             ## log info message
352             ##
353            
354 0     0   0 my $self = shift;
355            
356 0 0       0 $self->{logger}->info(@_) if $self->{logger};
357             }
358              
359             ###########################################################
360              
361             sub _session {
362            
363             ##
364             ## get reference on CGI::Session object
365             ##
366            
367 2     2   5 my $self = shift;
368            
369 2         20 return $self->{session};
370             }
371              
372             ###########################################################
373              
374             sub _cgi {
375            
376             ##
377             ## get reference on CGI object
378             ##
379            
380 0     0   0 my $self = shift;
381            
382 0         0 return $self->{cgi};
383             }
384              
385             ###########################################################
386              
387             sub _encpw {
388              
389             ##
390             ## encrypt password
391             ##
392            
393 0     0   0 my ($self, $password) = @_;
394              
395 0         0 return md5_hex($password);
396             }
397              
398             ###########################################################
399              
400             sub _loggedIn {
401            
402             ##
403             ## accessor to internal logged-in flag and session parameter
404             ##
405            
406 7     7   4003 my $self = shift;
407            
408 7 100       25 if (@_) {
409             # set internal flag
410 2 100       11 if ($self->{logged_in} = shift) {
411             # set session parameter
412 1         4 $self->_session->param("~logged-in", 1);
413             }
414             else {
415             # clear session parameter
416 1         5 $self->_session->clear(["~logged-in"]);
417             }
418 2         99 $self->_debug("(re)set logged_in: ", $self->{logged_in});
419             }
420            
421             # return internal flag
422 7         30 return $self->{logged_in};
423             }
424              
425             ###########################################################
426              
427             sub _url {
428            
429 0     0     my $self = shift;
430            
431 0           return $self->{url};
432             }
433              
434             ###########################################################
435             ###
436             ### end of code, module documentation below
437             ###
438             ###########################################################
439              
440             1;
441             __END__