Forum Discussion

Steven_Ruby_872's avatar
Steven_Ruby_872
Icon for Nimbostratus rankNimbostratus
Jan 17, 2006

more fun with jsessionid persistence

so it seems that some people in development, have decided that we shouldnt make cookies a requirement in our webapp. That means if a clients browser doesnt allow cookies the COOKIE persistence wont work.

 

 

What is the best way to use both the COOKIE persistence and if there is no cookie then use UIE persistence based on the jsessionid in the uri?

 

 

Anyone have ideas?

 

 

 

sr

8 Replies

  • I get the general idea. My problem is it doesnt work.

     

     

    in the middle of a session it will flip to another server, which means the user has to authenticate again. i also dont see a persistence table entry ever created.

     

     

     

    sr
  • Is anyone successfully doing this? From a tcpdump, here is what I am interpreting:

     

     

    1) Client sends initial request

     

    2) Server responds with JSESSIONID= cookie AND links with JSESSIONID= built in to URI

     

    3) BIGIP evaluates

     

    a) If cookie present, add persistence.

     

    b) If no cookie present, lookup jsessionid in URI and add persistence

     

     

    THe problem with both A & B is the persistence will be added on the 2nd load balancing decision, which may or may not be the original master server. This is easily solved with the cookie, as the persistence entry can be added on the HTTP_RESPONSE event. I'm struggling with the logic to :

     

     

    1) On the response event, create persistence entry for cookie and URI

     

    2) On the request event, if cookie persistence is used, delete the uri persistence entry and vice versa.

     

     

    One follow-up. If you are setting both via uie persistence, and the value (jsessionid, either from cookie or link) is the same, does one get overwritten? I guess it doesn't matter, since the value will be matched when evaluted on the http_request event when persisted via the cookie value or the $jsess value.
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    For setting the persistence entry on the response, the final rule in this post worked: (Click here) , although as noted, the server /can/ set more than one Set-Cookie header when setting multiple cookies, so you might need to do some additional coding to find it.

    I've used variations on the theme for a couple of other customers since, for both ASP & jsession ID's, and it seems to do the trick. (We have not yet run into multiple Set-Cookie headers.)

    You'd just need to add condtional logic in the request event to look for the cookie then fall back the URI if no cookie:
      
    if {[HTTP::cookie exists ASP.NET_SessionId] }{
       set SessionId [HTTP::cookie ASP.NET_SessionId] 
    else {
       set SessionId [HTTP::uri findstr "ASP.NET_SessionId=" 17 24]
    }
    (of course adjusting the offset / length of findstr to match your cookie name & value lengths)

    Since the cookie will be set by the server regardless of whether the client will ever use it, I think you're safe to exclusively extract the value from the Set-Cookie header, rather than from the payload.

    Your last statement is correct. The request event /could/ conditionally use cookie persistence in the presence of the cookie, but since you're creating the uie persistence record, probably easier & more consistent to just use that. (Otherwise I think you might have to coordinate expiry of the cookie with expiry of the persistence record... not sure, I'll leave that for you to think through.)

    HTH

    /deb
  • I am setting the persistence on the first server response for clients who disable cookies. For clients who enable cookies, is it better (read--more efficient) to persist them with cookie insert, or write the persistence for the jsessionid cookie into the rule I'm using to persist the cookie-disabled clients? If I stick with cookie insert, I can delete the persistence entry from the table for clients who return with cookies, and maintain the entries for clients who do not. If I use the jsessionid cookie, then I must maintain persistence entries for all clients.
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account

     

    Tough question... You could try it both ways under load with rule timing enabled to determine the most efficient approach.

     

     

    If you delete the persistence entry for a cookie-enabled client, that would reduce the size of the persistence table, reducing memory footprint & CPU cycles to parse through it, but I'm not sure if that's a likely bottleneck.

     

     

    If you were to delete the persistence entry for any request w/a cookie, you'd have to search for it in the persistence table on each such request, which would increase the CPU cycles required for rule processing, perhaps offsetting the advantage gained above.

     

     

    Aside from that, I'd say using uie persistence with a defined timeout for both is more deterministic, since the timeout is managed locally, and also seems be more administratively efficient. With cookies w/expiry, client clock variations may skew the cookie timeout, and if you resort to session cookies instead, you would have different session management behaviour for the 2 sets of clients.

     

     

    HTH

     

    /deb
  • The non-cookie persistence does not work unless I have oneconnect enabled. Is this by design? My rule:

    
    when HTTP_RESPONSE {
      if { [HTTP::cookie exists "JSESSIONID"] } {
        set trimID [lindex [split  [HTTP::cookie "JSESSIONID"] "!" ] 0]
        if { [persist lookup uie $trimID] equals "" } { 
          persist add uie $trimID 1800
          log "added persistent entry $trimID for server [LB::server addr]"
        } else { log "continued sessionID $trimID for server [LB::server addr]" }
      }
    }
    when HTTP_REQUEST {
      if { [active_members MyPool] == 0 } {
        HTTP::redirect "http://[HTTP::header "X-Forwarded-Host"]/myUri.html"
      }
      if { [HTTP::header exists "X-Forwarded-Host"] } {
        HTTP::header replace "Host" [HTTP::header "X-Forwarded-Host"]
      }
      if { not [HTTP::cookie exists "MyCookie"] } {
        set jsess [findstr [HTTP::uri] "jsessionid" 11 "!"]
        if { $jsess != "" } {
        persist uie $jsess 1800
        log "Used URI, value is $jsess, server [LB::server addr]"
        }
      } else {
           log "used Cookie Insert, value is [HTTP::cookie "MyCookie"]" 
        }
    }
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Without OneConnect enabled, only the first request in a Keep-Alive connection is parsed for persistence data, so if multiple requests are sent on the same Keep-Alive connection, LTM will persist them all to the same destination as the first.

     

     

    A OneConnect profile with mask of 255.255.255.255 will allow parsing of all requests and serverside connections will only be re-used for the same client.

     

     

    HTH

     

    /deb