|
| 1 | +<!-- |
| 2 | +{ |
| 3 | + "title": "Session Handling in Lucee", |
| 4 | + "id": "session-handling", |
| 5 | + "related": [ |
| 6 | + "application-cfc", |
| 7 | + "request-handling", |
| 8 | + "caching" |
| 9 | + ], |
| 10 | + "categories": [ |
| 11 | + "server", |
| 12 | + "state-management", |
| 13 | + "configuration" |
| 14 | + ], |
| 15 | + "description": "Comprehensive guide on session handling and configuration in Lucee, including session types, storage options, and security considerations.", |
| 16 | + "keywords": [ |
| 17 | + "Session Management", |
| 18 | + "CFML Sessions", |
| 19 | + "JEE Sessions", |
| 20 | + "Session Storage", |
| 21 | + "Session Security", |
| 22 | + "Session Timeout", |
| 23 | + "Session Clustering", |
| 24 | + "State Management" |
| 25 | + ] |
| 26 | +} |
| 27 | +--> |
| 28 | + |
| 29 | +# Session Handling |
| 30 | + |
| 31 | +This document explains how session handling works in Lucee and covers configuration options, storage mechanisms, and security considerations. |
| 32 | + |
| 33 | +## Type |
| 34 | +Lucee allows use of 2 types of sessions: |
| 35 | +- "jee" - The session provided and managed by the ServletEngine, also known as "JSession" |
| 36 | +- "cfml" - The Sessions provided and managed by Lucee |
| 37 | +You can define the type used in the Lucee Administrator or .CFConfig.json like this |
| 38 | +```json |
| 39 | +{ |
| 40 | + sessionType: "cfml" |
| 41 | +} |
| 42 | +``` |
| 43 | + and overwrite it in the Application.cfc like this |
| 44 | +```javascript |
| 45 | +this.sessionType="cfml"; |
| 46 | +``` |
| 47 | + |
| 48 | +This document only addresses session type "cfml" , for "jee" (Servlet Engine Session) please see for example |
| 49 | +https://docs.oracle.com/cd/B31017_01/web.1013/b28959/sessions.htm#:~:text=When%20a%20servlet%20creates%20an,pair%20constitutes%20a%20session%20attribute. |
| 50 | + |
| 51 | +## Enable Sessions |
| 52 | + |
| 53 | +You can enable session management in the Lucee Administrator or .CFConfig.json like this |
| 54 | +```json |
| 55 | +{ |
| 56 | + sessionManagement: true |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | + and overwrite it in the Application.cfc like this |
| 61 | +```javascript |
| 62 | +this.sessionManagement=true; |
| 63 | +``` |
| 64 | +By default sessions are enabled |
| 65 | + |
| 66 | +## (Idle)Timeout |
| 67 | +You can set the default session idle timeout in the Lucee Administrator or .CFConfig.json like this |
| 68 | +```json |
| 69 | +{ |
| 70 | + sessionTimeout: "0,0,30,0" |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | + by default it is 30 minutes. |
| 75 | + and overwrite it in the Application.cfc like this |
| 76 | +```javascript |
| 77 | +this.sessionTimeout=createTimeSpan(0,0,30,0); // 30 minutes |
| 78 | +this.sessionTimeout=1/24/2; // 30 minutes |
| 79 | +``` |
| 80 | + |
| 81 | +## Storage |
| 82 | +Lucee allows to define a storage for sessions, by default this is "memory", what means that the session is simply stored in memory for the full life cycle of the session. |
| 83 | +You can set the default session storage in the Lucee Administrator or .CFConfig.json like this |
| 84 | +```json |
| 85 | +{ |
| 86 | + sessionStorage: "memory" |
| 87 | +} |
| 88 | +``` |
| 89 | + and overwrite it in the Application.cfc like this |
| 90 | +```javascript |
| 91 | +this.sessionStorage="memory"; |
| 92 | +``` |
| 93 | + |
| 94 | +for any other setting than "memory", the session is only stored up to a minute (idle) in memory, after that it is removed from memory and loaded again from the storage on demand. |
| 95 | + |
| 96 | +The following settings are possible: |
| 97 | +- "memory" - simply store in memory for the full life cycle |
| 98 | +- "cookie" - stored in the cookie of the user (should be avoided from a security perspective) |
| 99 | +- "file" - stored in a local file |
| 100 | +- <datasource-name> - name of an existing datasource, the session get stored in a table with name "cf_session_data" in that datasource. |
| 101 | +- <cache-name> - name of an existing cache, the session get stored in that cache, for example Redis. |
| 102 | + |
| 103 | +Lucee does not store "empty" sessions into a storage, so when a session does not contain any data other than the default keys, it not get stored. |
| 104 | + |
| 105 | +### Distributed Storage |
| 106 | +In case you are using a cache or a datasource as storage you can define how the data synchronization between local memory and storage should work. |
| 107 | +You can set the default session distribution mode in the Lucee Administrator or .CFConfig.json like this |
| 108 | +```json |
| 109 | +{ |
| 110 | + sessionCluster: false |
| 111 | +} |
| 112 | +``` |
| 113 | + and overwrite it in the Application.cfc like this |
| 114 | +```javascript |
| 115 | +this.sessionCluster=false; |
| 116 | +``` |
| 117 | +If set to `false`, the local memory acts as primary storage point. When Lucee has the session locally at the beginning of a request, it will not retrieve the data from storage, only updating the storage at the end when the data is modified. This setting is optimal when the storage is used by a single server as it minimizes storage requests. |
| 118 | + |
| 119 | +If set to `true`, the external storage acts as the primary source of truth. The data is checked against the storage at the beginning of every request to ensure consistency. This setting is recommended when the storage is shared between multiple servers to ensure data consistency across the cluster. |
| 120 | + |
| 121 | +## Invalidate |
| 122 | +The `SessionInvalidate()` function immediately terminates the current session and removes all associated data. This is useful when you need to clear all session data, such as during user logout. Example: |
| 123 | + |
| 124 | +```javascript |
| 125 | +SessionInvalidate(); |
| 126 | +// All session variables are now cleared |
| 127 | +``` |
| 128 | + |
| 129 | +## Rotate |
| 130 | +The `SessionRotate()` function creates a new session and copies all existing session data to it, while invalidating the old session. This is a security measure typically used after authentication state changes (login/logout) to prevent session fixation attacks. Example: |
| 131 | + |
| 132 | +```javascript |
| 133 | +// User logs in successfully |
| 134 | +SessionRotate(); |
| 135 | +// Session data is preserved but with a new session ID |
| 136 | +``` |
| 137 | + |
| 138 | +## Security |
| 139 | +The Session is linked with help of the key "CFID" that can be in the URL of the cookie of the user (the key "CFTOKEN" is not used by Lucee and only exists for compatibility with other CFML engines). |
| 140 | +Lucee first checks for "CFID" in the URL and only if not exists in the URL it looks for it in the cookie scope. |
| 141 | + |
| 142 | +Since Lucee 6.1, Lucee only accepts the key in the URL in case it has active sessions in memory with that key. |
| 143 | +So in case you are using a storage (not "memory"), this is only up to a minute. |
| 144 | + |
| 145 | +Since Lucee 6.1 you can completely block the use of CFID in the url by setting the following system property |
| 146 | +``` -Dlucee.read.cfid.from.url=false``` |
| 147 | +or environment variable |
| 148 | +``` LUCEE_READ_CFID_FROM_URL=false``` |
| 149 | + |
| 150 | + |
| 151 | + |
| 152 | +## Best Practice |
| 153 | +Lucee tries to avoid creating sessions whenever possible. It only creates a session when: |
| 154 | +- Session data is read or written in the code |
| 155 | +- A key in the session scope is checked |
| 156 | +- The Application.cfc contains session listeners like "onSessionStart" or "onSessionEnd" |
| 157 | + |
| 158 | +Best practices for session handling: |
| 159 | +1. Avoid unnecessary session creation by only accessing the session scope when needed |
| 160 | +2. Use appropriate storage mechanisms based on your deployment architecture |
| 161 | +3. Consider security implications when choosing between URL and cookie-based session tracking |
| 162 | +4. Implement session rotation after authentication state changes |
| 163 | +5. Set appropriate timeout values based on your application's requirements |
| 164 | + |
| 165 | +Since Lucee 6.2, empty sessions are only kept for up to a minute, independent of the storage used, to optimize resource usage. |
0 commit comments