Here is an example which generates a session ID and inserts it in an HTTP cookie in responses as well as the session table. On requests, if the session ID exists in the cookie, the value is verified against the session table entry. The session table entry can be accessed from rules on multiple virtual servers. The rule uses the 'any virtual' option for the session command to do this. The string "some_session_value" could be generated dynamically or set statically.
Aaron
Tested on 9.4.5. If used on versions lower than 9.4, the [virtual] command
(used to get the virtual server name) must be replaced with [virtual name].
when RULE_INIT {
set ::session_cookie_domain "example.com"
set ::session_timeout 600
}
when HTTP_REQUEST {
log local0. " [IP::client_addr]:[TCP::client_port] [virtual]: New HTTP request to [HTTP::uri], with session cookie:\
[HTTP::cookie value ClientID]."
Initialize local variable to track whether to add the client ID to the session table
set session_readd 0
Initialize local variable to track whether to insert a cookie in the response
set insert_cookie 0
Check if client request contains the ClientID cookie
if {[string length [HTTP::cookie value ClientID]]}{
log local0. " [IP::client_addr]:[TCP::client_port] [virtual]: ClientID cookie [HTTP::cookie value ClientID]\
session table value: [session lookup uie [list [HTTP::cookie value ClientID] any virtual]]"
Check if there is not a session table entry which corresponds to the ClientID cookie value
if { [session lookup uie [list [HTTP::cookie value ClientID] any virtual]] eq "" } {
set valid_session 0
log local0. " [IP::client_addr]:[TCP::client_port] [virtual]: Client had cookie with session ID\
[HTTP::cookie value ClientID], but session table entry didn't exist."
} else {
Save the client ID from the cookie
set client_id [HTTP::cookie value ClientID]
Track that we want to update the session table entry for this client ID (update the expiry time)
set session_readd 1
set valid_session 1
log local0. " [IP::client_addr]:[TCP::client_port] [virtual]: Client had cookie with session ID\
[HTTP::cookie value ClientID], session table entry [session lookup uie [list [HTTP::cookie value ClientID] any virtual]]."
}
} else {
set valid_session 0
}
If the client didn't have a valid session, perform some test to determine whether we want to allow
the request and/or give the client a new session in the response
if {not ($valid_session)}{
This test is based on the business logic. Do we want to allow a new session to the application?
if {$::some_test_is_true}{
set insert_cookie 1
} else {
HTTP::redirect "https://busy.example.com"
set insert_cookie 0
}
}
}
when HTTP_RESPONSE {
If the client side flagged that we need a cookie, generate one and add an entry to the session table.
if { $insert_cookie } {
Generate a random 8 digit number for the client ID value
set client_id [format "%08d" [expr { int(100000000 * rand()) }]]
Insert a cookie in the response named ClientID with the random number as the value.
Set the domain on the cookie so the browser will send it to another subdomain
HTTP::cookie insert name "ClientID" value $client_id domain $::session_cookie_domain
Add the clientID to the session table (some_session_value could be generated dynamically or set statically).
session add uie [list $client_id any virtual] some_session_value $::session_timeout
log local0. "[IP::client_addr]:[TCP::client_port] [virtual]: Added cookie and session table entry for $client_id:\
[session lookup uie [list $client_id any virtual]]"
}
We either need to refresh, or re-add a ClientID cookie in the table
if { $session_readd } {
Add the clientID to the session table (some_session_value could be generated dynamically or set statically).
session add uie [list $client_id any virtual] some_session_value $::session_timeout
log local0. "[IP::client_addr]:[TCP::client_port] [virtual]: Added/updated session table entry for $client_id:\
[session lookup uie [list $client_id any virtual]]"
}
}
Log output:
Request with no cookie to VIP 1
: 172.31.42.20:4267 http_1_vs: New HTTP request to /test/index.page, with session cookie: .
: 172.31.42.20:4267 http_1_vs: Added cookie and session table entry for 76486291: some_session_value
Request with valid cookie to VIP 1
: 172.31.42.20:4269 http_1_vs: New HTTP request to /test/index.page, with session cookie: 76486291.
: 172.31.42.20:4269 http_1_vs: ClientID cookie 76486291 session table value: some_session_value
: 172.31.42.20:4269 http_1_vs: Client had cookie with session ID 76486291, session table entry some_session_value.
: 172.31.42.20:4269 http_1_vs: Added/updated session table entry for 76486291: some_session_value
Request with valid cookie to VIP 2
: 172.31.42.20:4271 http_2_vs: New HTTP request to /test/index.page, with session cookie: 76486291.
: 172.31.42.20:4271 http_2_vs: ClientID cookie 76486291 session table value: some_session_value
: 172.31.42.20:4271 http_2_vs: Client had cookie with session ID 76486291, session table entry some_session_value.
: 172.31.42.20:4271 http_2_vs: Added/updated session table entry for 76486291: some_session_value
Request with valid cookie to VIP 1
: 172.31.42.20:4273 http_1_vs: New HTTP request to /test/index.page, with session cookie: 76486291.
: 172.31.42.20:4273 http_1_vs: ClientID cookie 76486291 session table value: some_session_value
: 172.31.42.20:4273 http_1_vs: Client had cookie with session ID 76486291, session table entry some_session_value.
: 172.31.42.20:4273 http_1_vs: Added/updated session table entry for 76486291: some_session_value
And here is the session entry viewed through the persistence table output
b persist mode universal show all
PERSISTENT CONNECTIONS
| Mode universal Value 76486291
| virtual 10.41.135.2:http node 10.41.135.3:http age 16sec