Apache-AppSamurai
view release on metacpan or search on metacpan
lib/Apache/AppSamurai.pm view on Meta::CPAN
unless (scalar(keys %{$sessconfig})) {
$self->Log($r, ('error', "GetSessionConfig(): No Session configuration found for $auth_name!"));
return undef;
}
## TODO - This section of session autoconfig/defaults is pretty
## inflexilbe and too tightly tied to HMAC_SHA and CryptBase64.
## It should be abolished or moved out and into a generalized
## pre-config module that can be called ONCE (at startup)
# Use files for storage and locking by default
(exists($sessconfig->{Store})) || ($sessconfig->{Store} = "File");
(exists($sessconfig->{Lock})) || ($sessconfig->{Lock} = "File");
# If files are being used, paths must be set
if ($sessconfig->{Store} eq 'File' && !exists($sessconfig->{Directory})) {
$self->Log($r, ('error', "GetSessionConfig(): ${auth_name}SessionDirectoy must be defined for the File session store"));
return undef;
}
if ($sessconfig->{Lock} eq 'File' && !exists($sessconfig->{LockDirectory})) {
$self->Log($r, ('error', "GetSessionConfig(): ${auth_name}SessionLockDirectoy must be defined for the File session lock"));
return undef;
}
# Use HMAC_SHA and CryptBase64 for session creation and serialization
# by default.
(exists($sessconfig->{Generate})) || ($sessconfig->{Generate} = "AppSamurai/HMAC_SHA");
(exists($sessconfig->{Serialize})) || ($sessconfig->{Serialize} = "AppSamurai/CryptBase64");
# Check/clean ServerPass if present (else assume ServerKey set)
if (exists($sessconfig->{ServerPass})) {
# Set the key (note - GetServerKey logs the error, if any)
($sessconfig->{ServerKey} = $self->GetServerKey($r)) || (return undef);
}
# We have to have a ServerKey at this point, in hex form.
if (($sessconfig->{Generate} =~ /HMAC/i) || ($sessconfig->{Serialize} =~ /Crypt/i)) {
unless (CheckSidFormat($sessconfig->{ServerKey})) {
# Bad server key format
$self->Log($r, ('error', "GetSessionConfig(): You must a valid ${auth_name}ServerPass or ${auth_name}ServerKey!"));
return undef;
}
# For speed, SerializeCipher should be set in the config
if (!$sessconfig->{SerializeCipher}) {
# Attempt to load CryptBase64 module
unless (eval "require Apache::AppSamurai::Session::Serialize::CryptBase64") {
$self->Log($r, ('error', "GetSessionConfig(): Could not load CryptBase64 while attempting to auto-select ${auth_name}SerializeCipher value: $!"));
return undef;
}
# Use CryptBase64 cipher detection utility (Slower)
unless ($sessconfig->{SerializeCipher} = &Apache::AppSamurai::Session::Serialize::CryptBase64::find_cipher()) {
# None found. (Note - Check @allowedciphers in CryptBase64.pm
# for supported ciphers)
$self->Log($r, ('error', "GetSessionConfig(): Could not auto-detect a suitable ${auth_name}SerializeCipher value (Please configure manualy): $!"));
return undef;
}
}
}
# Set a 1hr Timeout if neither Timeout or Expire are set
unless ($sessconfig->{Timeout} || $sessconfig->{Expire}) {
$sessconfig->{Timeout} = 3600;
}
return $sessconfig;
}
# Compute/check server key from server pass, returning key.
sub GetServerKey {
my ($self, $r) = @_;
my $auth_name = ($r->auth_name()) || (die("GetServerKey(): No auth name defined!\n"));
my $dirconfig = $r->dir_config;
my $serverkey = '';
if (exists($dirconfig->{$auth_name . "SessionServerPass"})) {
my $serverpass = $dirconfig->{$auth_name . "SessionServerPass"};
unless ($serverpass =~ s/^\s*([[:print:]]{8,}?)\s*$/$1/s) {
$self->Log($r, ('error', "GetServerKey(): Invalid ${auth_name}SessionServerPass (must be use at least 8 printable characters"));
return undef;
}
if ($serverpass =~ /^(password|serverkey|serverpass|12345678)$/i) {
$self->Log($r, ('error', "GetServerKey(): ${auth_name}SessionServerPass is $1... That is too lousy"));
return undef;
}
unless ($serverkey = HashPass($serverpass)) {
$self->Log($r, ('error', "GetServerKey(): Problem computing server key hash for ${auth_name}SessionServerPass"));
return undef;
}
} elsif (exists($dirconfig->{$auth_name . "SessionServerKey"})) {
$serverkey = $dirconfig->{$auth_name . "SessionServerKey"};
} else {
$self->Log($r, ('error', "GetServerKey(): You must define either ${auth_name}SessionServerPass or ${auth_name}SessionServerKey in your Apache configuration"));
return undef;
}
# Check for valid key format
unless (CheckSidFormat($serverkey)) {
# Not good, dude. This should not happen
$self->Log($r, ('error', "GetServerKey(): Invalid server session key (CheckSidFormat() failure) for $auth_name"));
return undef;
}
return $serverkey;
}
# Apply the configured BasicAuthMap to the passed in credentials
# BasicAuthMap allows for flexibly parsing a single line of authentication
# data into multiple credentials in any order. (Keep those users happy...)
# Returns an array with the parsed credentials in order, or an empty set on
# failure.
sub ApplyAuthMap {
my ($self, $r, $pass, $amc) = @_;
my $auth_name = ($r->auth_name) || ('');
my ($o, $m, $i, @ct);
my @creds = ();
lib/Apache/AppSamurai.pm view on Meta::CPAN
}
}
return $keytext;
}
# Initiate a new session and return a session key. Takes the $r request (for
# record keeping), the username, and an optional "alter list" to be used
# to change cookies and/or headers sent from the proxy to the backend server.
sub CreateSession {
my ($self, $r, $username, $alterlist) = @_;
(defined($alterlist)) || ($alterlist = {});
my (%sess, $sid, $sessconfig, $kt);
# Extract the session config
($sessconfig = $self->GetSessionConfig($r)) || (die "CreateSession(): Unable to get session configuration while creating new session");
# Create a session auth key to send back to send back as the cookie
# value, and to use the HMAC-SHA and optional session file encryptor.
# FetchKeysource returns "" by default, resulting in a fully randomized
# key.
$kt = $self->FetchKeysource($r);
if (defined($kt)) {
$sessconfig->{key} = CreateSessionAuthKey($kt);
} else {
$self->Log($r, ('warn', "CreateSession(): Failed to generate session authentication key: Session creation denied"));
return undef;
}
# Check for valid looking key
unless (CheckSidFormat($sessconfig->{key})) {
$self->Log($r, ('warn', "CreateSession(): Bad session authentication key returned! Session creation denied"));
return undef;
}
# Run against the unique session tracker if configured. (*Don't make
# the same session twice)
if ($sessconfig->{Unique}) {
unless ($self->CheckTracker($r, 'SessionUnique', $sessconfig->{key})) {
$self->Log($r, ('warn', "CreateSession(): SessionUnique detected duplicate session authentication key! Session creation denied"));
return undef;
}
}
# Wrapped this in an eval, since Apache:Session dies on failures
eval { tie(%sess, 'Apache::AppSamurai::Session', undef, $sessconfig); };
if ($@) {
$self->Log($r, ('error', "CreateSession(): Unable to create new session: $@"));
return undef;
}
$sid = $sess{_session_id};
# Make sure we received a good session ID.
(CheckSidFormat($sid)) || (($self->Log($r, ('error', 'CreateSession(): Invalid Session ID Format on new Session'))) && (return undef));
$self->Log($r, ('notice', "LOGIN: username=\"$username\", session=\"$sid\""));
# Store some basics
$sess{'username'} = $username;
$sess{'ctime'} = time();
# Track last access time if Timeout is set
if ($sessconfig->{Timeout}) {
$sess{'atime'} = $sess{'ctime'};
$sess{'Timeout'} = $sessconfig->{Timeout};
}
# Set hard expiration time if Expire is set
if ($sessconfig->{Expire}) {
$sess{'etime'} = $sess{'ctime'} + $sessconfig->{Expire};
$sess{'Expire'} = $sessconfig->{Expire};
}
# Apply passback cookies to response, and pull in updated alterlist
if (defined($alterlist->{cookie})) {
$alterlist = $self->AlterlistPassBackCookie($alterlist, $r);
}
# If present, save Authorization header to detect future changes,
# then prepend an alterlist rule to delete the header to prevent
# pass though to the backend server. (If needed, a separate
# alterlist rule to add an Authorization header should be set
# by a auth module.)
if ($r->headers_in->{"Authorization"}) {
$sess{'Authorization'} = $r->headers_in->{"Authorization"};
# Stick it in front in case we have an existing add
# header from an auth module
unshift(@{$alterlist->{header}}, 'delete:Authorization:');
}
# Save current alterlist to session
$self->AlterlistSave($alterlist, \%sess);
# Release session
untie(%sess);
# Return the session auth key
return $sessconfig->{key};
}
# Destroy a session, rendering it forever useless. Takes a request hash ref
# and a session hash ref as args. (Session must be tied when DestroySession
# is called.)
sub DestroySession {
my ($self, $r, $sess) = @_;
# Call the delete method for the the tied hash. Wrapped in eval goodness
# since Apache::Session will die on error.
eval { tied(%{$sess})->delete; };
if ($@) {
$self->Log($r, ('warn', "DestroySession(): Unable to destroy session: $@"));
return undef;
}
return 1;
}
## TRACKER - A system to store persistant and shared data for various
## uses. This is yet more code that could be refactored and busted into
## external modules to allow for adding arbitrary stateful checks of
## all sorts of things, (like the authentication handlers).
## For now, only a small set of tracker types are provided,
## and all are defined in this module.
lib/Apache/AppSamurai.pm view on Meta::CPAN
sub CheckTrackerAuthUnique {
my $trak = shift;
my $ch = HashAny(@_);
my $time = time();
# If defined, the jig is up!
if ($trak->{$ch}) {
die("CheckTrackerAuthUnique(): RULE VIOLATION: credkey=$ch\n");
} else {
# Set value to
$trak->{$ch} = 'ts' . $time . ":cnt1";
}
return 1;
}
# Check given tracker hash ($_[0]), make sure we have not seen the same
# session authentication key (cookie) before. Stores a hash of session key
# string to minimize security risk.
sub CheckTrackerSessionUnique {
my $trak = shift;
my $ch = HashAny(@_);
my $time = time();
# If defined, the jig is up!
if ($trak->{$ch}) {
die("CheckTrackerSessionUnique(): RULE VIOLATION: sesskey=$ch\n");
} else {
# Set value to
$trak->{$ch} = 'ts' . $time . ":cnt1";
}
return 1;
}
# Check the last access time stamp, and update if needed, for a given session.
# Does NOT update the time if a fixed timeout has been set.
# Returns undef if the atime is more than the session's timeout age
# or if etime is set and is over the session's expire age.
sub CheckTime {
my ($self, $sess) = @_;
my $time = time();
my $tdiff;
my $ret = undef;
# All sessions require at least a floating or fixed timeout!
($sess->{atime} || $sess->{etime}) or return undef;
# Check the hard timeout first, if it exists.
# This short circuits further checking since the hard timeout is king!
if ($sess->{etime}) {
if ($time >= $sess->{etime}) {
return undef;
} else {
$ret = $sess->{etime};
}
}
if ($sess->{atime}) {
$tdiff = $time - $sess->{atime};
if ($tdiff < $sess->{Timeout}) {
# We are still valid. Update the time if we are over 60 seconds
# stale.
if ($tdiff >= 60) {
$sess->{atime} = $time;
}
$ret = $sess->{atime};
} else {
return undef;
}
}
return $ret;
}
# The Alterlist functions manipulate and apply a list of transforms to apply to
# the headers and cookies of the client request before sending the request
# through to the backend server. $self->{alterlist} is a hash containing
# one or more of the following container arrays:
#
# header
# ------
# @{$self->{alterlist}->{header}} - One or more header transforms, with the
# syntax:
# ACTION:NAME:VALUE
# ACTION - add, replace, or delete
# NAME - Header name (or regex match for delete)
# VALUE - New value of header for add or replace, else optional regex filter
# for delete (Prefix pattern with ! for negation)
#
# cookie
# ------
# @{$self->{alterlist}->{cookie}} - One or more cookie transforms, with the
# syntax:
# ACTION:NAME:VALUE
# ACTION - add, replace, delete, or passback
# NAME - Cookie name (or regex match for delete)
# VALUE - New value of cookie, or regex filter for delete action (Prefix
# pattern with ! for negation)
#
# Note - delete rules with optional value match pattern will delete only values
# of a multi-value cookie that match the value pattern
#
# The special "passback" action passes cookies back to the web browser on
# login, This allows us to gather cookies from backend servers on login, but
# have the web browser maintain them.
#
# More containers can be added without modifying the generic functions.
# Load Alterlist rules from session and return a ref to the loaded alterlist
sub AlterlistLoad {
my ($self, $sess) = @_;
my ($sk,$rk);
my $alterlist = {};
# All alterlist save value start with al-
foreach $sk (keys %{$sess}) {
($sk =~ /^al\-([\w]+)$/) || (next);
$rk = $1;
@{$alterlist->{$rk}} = split("\n", $sess->{$sk});
lib/Apache/AppSamurai.pm view on Meta::CPAN
PerlSetVar BobAuthBasicLoginUrl C<https://bob.org/login>
For AuthName C<Bob>, set the C<LoginUrl> for the C<AuthBasic> authentication
module to C<https://bob.org/login>
See L<Apache::AppSamurai::AuthBase> for general authentication module
information. If you need an authentication type that is not supported
by the authentication modules shipped with AppSamurai, and is not
available as an add on module, please review L<Apache::AppSamurai::AuthBase>
and use the skeletal code from AuthTest.pm, which is included under
/examples/auth/ in the AppSamurai distribution.
=head2 SESSION CONFIGURATION
Each Apache::AppSamurai instance must have its local (proxy server side)
session handling defined.
L<Apache::Session|Apache::Session> provides the majority of the session
framework. Around Apache::Session is wrapped
L<Apache::AppSamurai::Session|Apache::AppSamurai::Session>, which
adds features to allow for more flexible selection of sub-modules.
Most Apache::Session style configuration options can be passed directly to the
session system by prefixing them with C<authnameSession>.
Module selection is slightly different than the default supplied with
Apache::Session. Plain names, without any path or ::, are handled
exactly the same: Modules are loaded from within the Apache::Session
tree. Two additional alternatives are provided:
=over 4
=item *
I<AppSamurai/MODULE> - Load I<MODULE> from under the
B<Apache::AppSamurai::Session> tree instead of the B<Apache::Session> tree.
=item *
I<PATH::MODULE> - Load I<PATH::MODULE> literally. Note - Since :: is required
to be present, a root module name will not work.
=back
The most common configuration options follow. See
L<Apache::AppSamurai::Session|Apache::AppSamurai::Session> and
L<Apache::Session|Apache::Session> for
more advanced options, like using a database for storage.
B<NOTE> - "Session" is shown prepending each of these directives, Inside
the L<Apache::AppSamurai::Session|Apache::AppSamurai::Session> and
L<Apache::Session|Apache::Session> documentation, "Session" is omitted.
=head3 SessionI<Expire> C<SECONDS>
(Default: 0)
The maximum session lifetime in seconds. After a user has been logged in this
long, they are logged out. (Ignores weather the user is idle or not.)
=head3 SessionI<Timeout> C<SECONDS>
(Default: 3600 (1 hour)).
The maximum time a session can be idle before being removed. After a user has
not accessed the protected application for this many seconds, they are logged
out.
=head3 SessionI<Store> C<NAME>
(Default: File)
The session storage module name. "File" is the default, which maps to
B<Apache::Session::Store::File|Apache::Session::Store::File>
(Note - See the top of this section,
L</SESSION CONFIGURATION>, for details on the three ways to specify a path
for this option and the following options that point to a module.)
=head3 SessionI<Lock> C<NAME>
(Default: File)
The session locking module name. "File" is used by default, which maps to
B<Apache::Session::Lock::File|Apache::Session::Lock::File>
=head3 SessionI<Generate> C<NAME>
(Default: AppSamurai/HMAC_SHA)
The session ID generator module name. "AppSamurai/HMAC_SHA" is used by default,
which maps to
L<Apache::AppSamurai::Session::Generate::HMAC_SHA|Apache::AppSamurai::Session::Generate::HMAC_SHA>
This special module takes a server key and a session authentication key and
returns a HMAC code representing the local ("real") session ID. (Input and
output are all SHA256 hex strings that are passed in using the sessionconfig
hash.)
As this is tied closely into the current Apache::AppSamurai code, please do
not use an alternate serializer without first reviewing the related code.
=head3 SessionI<Serialize> C<NAME>
(Default: AppSamurai/CryptBase64)
The session data serializer module. "AppSamurai/CryptBase64" is used by
default, which maps to
L<Apache::AppSamurai::Session::Serialize::CryptBase64|Apache::AppSamurai::Session::Serialize::CryptBase64>
This special module uses server key and a session authentication key to
encrypt session data using a block cipher before Base64 encoding it.
(All keys are 256 bit hex strings.)
Base64 allows for storage in file, database, etc without worrying about binary
data issues. In addition, this module allows for safer storage of data on
disk, requiring both the local server key and the secret session key from the
user before unlocking the data.
L<Crypt::CBC|Crypt::CBC> is used with a support block cipher module to perform
encryption/decryption. (See the next section for information on
configuring a cipher.)
As this is tied closely into the current Apache::AppSamurai code, please do not
use an alternate serializer without first reviewing the related code.
=head3 SessionI<SerializeCipher> C<CIPHER_MODULE>
(Default: undef)
lib/Apache/AppSamurai.pm view on Meta::CPAN
# PerlModule ModPerl::Registry
# Load the main module and define configuration options for the
# "Example" auth_name
PerlModule Apache::AppSamurai
PerlSetVar ExampleDebug 0
PerlSetVar ExampleCookieName MmmmCookies
PerlSetVar ExamplePath /
PerlSetVar ExampleLoginScript /login.pl
# Defaults to All by may also be Any
#PerlSetVar ExampleSatisty All
# Optional session cookie domain (Avoid unless absolutely needed.)
#PerlSetVar ExampleDomain ".thing.er"
# Require secure sessions (default: 1)
#PerlSetVar ExampleSecure 1
# Set proprietary MS flag
PerlSetVar ExampleHttpOnly 1
# Define authentication sources, in order
PerlSetVar ExampleAuthMethods "AuthRadius,AuthBasic"
# Custom mapping of xxxxxx;yyyyyy Basic authentication password input
# to specific and separate individual credentials. (default: undef)
PerlSetVar ExampleBasicAuthMap "2,1=(.+);([^;]+)"
## Apache::AppSamurai::AuthRadius options ##
# (Note - See L<Apache::AppSamurai::AuthRadius> for more info)
PerlSetVar ExampleAuthRadiusConnect "192.168.168.168:1645"
PerlSetVar ExampleAuthRadiusSecret "radiuspassword"
## Apache::AppSamurai::AuthBasic options.##
# (Note - See L<Apache::AppSamurai::AuthBasic> for more info)
# Set the URL to send Basic auth checks to
PerlSetVar ExampleAuthBasicLoginUrl "https://ex.amp.le/thing/login"
# Always send Basic authentication header to backend server
PerlSetVar ExampleAuthBasicKeepAuth 1
# Capture cookies from AuthBasic login and set in client browser
PerlSetVar ExampleAuthBasicPassBackCookies 1
# Abort the check unless the "realm" returned by the server matches
PerlSetVar ExampleAuthBasicRequireRealm "blah.bleh.blech"
# Pass the named header directly through to the AuthBasic server
PerlSetVar ExampleAuthBasicUserAgent "header:User-Agent"
## Session storage options ##
# (Note - See L<Apache::AppSamurai::Session> and L<Apache::Session> for
# more information.)
# Inactivity timeout (in seconds)
PerlSetVar ExampleSessionTimeout 1800
# Use the File storage and lock types from Apache::Session
PerlSetVar ExampleSessionStore "File"
PerlSetVar ExampleSessionLock "File"
# File storage options (Relevant only to File storage and lock types)
PerlSetVar ExampleSessionDirectory "/var/www/session/sessions"
PerlSetVar ExampleSessionLockDirectory "/var/www/session/slock"
# Use the Apache::AppSamurai::Session::Generate::HMAC_SHA generator
PerlSetVar ExampleSessionGenerate "AppSamurai/HMAC_SHA"
# Use the Apache::AppSamurai::Session::Serialize::CryptBase64
# data serializer module with Crypt::Rijndael (AES) as the block
# cipher provider
PerlSetVar ExampleSessionSerialize "AppSamurai/CryptBase64"
PerlSetVar ExampleSessionSerializeCipher "Crypt::Rijndael"
# Set the server's encryption passphrase (for use with HMAC session
# generation and/or encrypted session storage)
PerlSetVar ExampleSessionServerPass "This is an example passphrase"
## Tracker storage options ##
# Cleanup tracker entries that have not changed in 1 day
PerlSetVar ExampleTrackerCleanup 86400
# Block further login attempts from IPs that send 10 failures with
# no more than 60 seconds between each subsequent failure
PerlSetVar ExampleIPFailures "10:60"
# Force at least one credential to be unique per-login. (Requires
# token or other non-static authentication type.)
PerlSetVar ExampleAuthUnique 1
# Prohibit a new session from using the same session ID as a previous
# session. (Only relevant for non-random sessions that use the
# Keysource directive to calculate a pseudo-cookie.)
PerlSetVar ExampleSessionUnique 1
## Special AppSamurai directory options ##
# (These will vary widely depending on your specific setup and requirements.)
<Directory "/var/www/htdocs/AppSamurai">
AllowOverride None
deny from all
<FilesMatch "\.pl$">
SetHandler perl-script
Options +ExecCGI
AuthType Apache::AppSamurai
AuthName "Example"
PerlHandler Apache::Registry
#*FOR MODPERL2 USE:
#PerlResponseHandler ModPerl::Registry
allow from all
lib/Apache/AppSamurai.pm view on Meta::CPAN
AuthName "Example"
PerlHandler Apache::AppSamurai->login
#*FOR MODPERL2 USE:
#PerlResponseHandler Apache::AppSamurai->login
allow from all
</Files>
<Files LOGOUT>
SetHandler perl-script
AuthType Apache::AppSamurai
AuthName "Example"
PerlHandler Apache::AppSamurai->logout
#*FOR MODPERL2 USE:
#PerlResponseHandler Apache::AppSamurai->logout
allow from all
</Files>
</Directory>
<Directory "/var/www/htdocs/AppSamurai/images">
Options None
allow from all
</Directory>
# Protected/proxied resource config 1: Form based
<Directory "proxy:https://ex.amp.le/thing/*">
#*FOR MODPERL2 USE:
#<Proxy "https://ex.amp.le/thing/*">
AuthType Apache::AppSamurai
AuthName "Example"
PerlAuthenHandler Apache::AppSamurai->authenticate
PerlAuthzHandler Apache::AppSamurai->authorize
Order deny,allow
Allow from all
require valid-user
</Directory>
#*FOR MODPERL2 USE:
#</Proxy>
# Protected/proxied resource config 2: Basic auth
<Directory "proxy:https://ex.amp.le/thaang/*">
#*FOR MODPERL2 USE:
#<Proxy "https://ex.amp.le/thaang/*">
AuthType Basic
AuthName "Example"
PerlAuthenHandler Apache::AppSamurai->authenticate
PerlAuthzHandler Apache::AppSamurai->authorize
# Add some local overrides to this directory. (Has
# no affect on other directories/locations)
# Switch from an inactivity timeout to a hard expiration
PerlSetVar ExampleSessionExpire 3600
PerlSetVar ExampleSessionTimeout 0
# In lieu of cookies, calculate the session key using the
# basic auth header from the client, and an argument called
# "Sessionthing" from the request URL. (NOTE - Keysource
# should be used with care! Do not use it unless you are
# sure of what you are doing!!!)
PerlAddVar ExampleKeysource header:Authorization
PerlAddVar ExampleKeysource arg:Sessionthing
Order deny,allow
Allow from all
require valid-user
</Directory>
#*FOR MODPERL2 USE:
#</Proxy>
# Do not allow forward proxying
ProxyRequests Off
# Proxy requests for /thing/* to https://ex.amp.le/thing/*
RewriteRule ^/thing/(.*)$ https://ex.amp.le/thing/$1 [P]
# Similar for /thaang/*
RewriteRule ^/thaang/(.*)$ https://ex.amp.le/thaang/$1 [P]
# Redirect requests to / into our default app
RewriteRule ^/?$ /thing/ [R,L]
# Allow in AppSamurai requests to proxy server
RewriteRule ^/AppSamurai -
# Capture logout URL from app and send to a pseudo page mapped to logout()
RewriteRule ^/thing/logout\.asp$ /AppSamurai/LOGOUT
# Block all other requests
RewriteRule .* - [F]
#*FOR MODPERL2 YOU MUST UNCOMMENT AND PUT THE FOLLOWING INSIDE
# RELEVANT VirtualHost SECTIONS (For most Apache2 setups, this would be
# the "<VirtualHost _default_:443>" section inside ssl.conf)
#
## Enable rewrite engine inside virtualhost
#RewriteEngine on
## Inherit rewrite settings from parent (global)
#RewriteOptions inherit
## Enable proxy connections to SSL
#SSLProxyEngine on
=head1 EXTENDING
Additional authentication modules, tracking features, and other options
can be added to Apache::AppSamurai. In the case of authentication modules,
all that is required is creating a new module that inherits from
L<Apache::AppSamurai::AuthBase|Apache::AppSamurai::AuthBase>.
Other features may be more difficult to add. (Apache::AppSamurai could
use some refactoring.)
( run in 1.878 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )