Completed
Push — master ( fe33ea...90407f )
by Derek Stephen
07:41
created

SessionManager::getInstance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Del;
4
5
final class SessionManager
6
{
7
    /**
8
     *  As this is a singleton, construction and clone are disabled
9
     *  use SessionManager::getInstance() if you need the instance
10
     */
11
    private function __construct(){}
12
13
    private function __clone(){}
14
15
    /**
16
     * @return SessionManager|null
17
     */
18
    public static function getInstance()
19
    {
20
        static $inst = null;
21
        if ($inst === null) {
22
            $inst = new SessionManager();
23
        }
24
        return $inst;
25
    }
26
    
27
    /**
28
     * Creates a secure session
29
     * @param $name
30
     * @param int $lifetime
31
     * @param string $path
32
     * @param null $domain
33
     * @param null $secure
34
     */
35
    public static function sessionStart($name, $lifetime = 0, $path = '/', $domain = null, $secure = null)
36
    {
37
        // Set the cookie name before we start.
38
        session_name($name . '_Session');
39
40
        // Set the domain to default to the current domain.
41
        $domain = isset($domain) ? $domain : $_SERVER['SERVER_NAME'];
42
43
        // Set the default secure value to whether the site is being accessed with SSL
44
        $secure = isset($secure) ? $secure : isset($_SERVER['HTTPS']);
45
46
        // Set the cookie settings and start the session
47
        session_set_cookie_params($lifetime, $path, $domain, $secure, true);
48
49
        $id = session_id();
50
        if(empty($id)) {
51
            session_start();
52
        }
53
54
        // Make sure the session hasn't expired, and destroy it if it has
55
        if (self::validateSession()) {
56
57
            // Check to see if the session is new or a hijacking attempt
58
            if (!self::preventHijacking()) {
59
60
                // Reset session data and regenerate id
61
                $_SESSION = array();
62
                $_SESSION['ipAddress'] = $_SERVER['REMOTE_ADDR'];
63
                $_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
64
                self::regenerateSession();
65
66
                // Give a 5% chance of the session id changing on any request
67
            } elseif (self::shouldRandomlyRegenerate()) {
68
                self::regenerateSession();
69
            }
70
        } else {
71
            self::destroySession();
72
        }
73
    }
74
75
    private function shouldRandomlyRegenerate()
76
    {
77
        return rand(1, 100) <= 5;
78
    }
79
80
81
    /**
82
     * Checks session IP and user agent are still the same
83
     * @return bool
84
     */
85
    private static function preventHijacking()
86
    {
87
        if (!isset($_SESSION['ipAddress']) || !isset($_SESSION['userAgent'])) {
88
            return false;
89
        }
90
        if ($_SESSION['ipAddress'] != $_SERVER['REMOTE_ADDR']) {
91
            return false;
92
        }
93
        if ($_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT']) {
94
            return false;
95
        }
96
        return true;
97
    }
98
99
    /**
100
     *  Creates a fresh session Id to make it harder to hack
101
     *  If the site is very slow in parts increase the expiry time
102
     *  10 seconds is a good default which allows ajax calls to work
103
     *  without losing the session
104
     */
105
    private static function  regenerateSession()
106
    {
107
        // If this session is obsolete it means there already is a new id
108
        if (isset($_SESSION['OBSOLETE']) && $_SESSION['OBSOLETE'] == true) {
109
            return;
110
        }
111
112
        // Set current session to expire in 10 seconds
113
        $_SESSION['OBSOLETE'] = true;
114
        $_SESSION['EXPIRES'] = time() + 10;
115
116
        // Create new session without destroying the old one
117
        session_regenerate_id(false);
118
119
        // Grab current session ID and close both sessions to allow other scripts to use them
120
        $newSession = session_id();
121
        session_write_close();
122
123
        // Set session ID to the new one, and start it back up again
124
        session_id($newSession);
125
        session_start();
126
127
        // Now we unset the obsolete and expiration values for the session we want to keep
128
        unset($_SESSION['OBSOLETE']);
129
        unset($_SESSION['EXPIRES']);
130
    }
131
132
    /**
133
     * Checks whether the session has expired or not
134
     * @return bool
135
     */
136
    private static function validateSession()
137
    {
138
        if (isset($_SESSION['OBSOLETE']) && !isset($_SESSION['EXPIRES'])) {
139
            return false;
140
        }
141
142
        if (isset($_SESSION['EXPIRES']) && $_SESSION['EXPIRES'] < time()) {
143
            return false;
144
        }
145
146
        return true;
147
    }
148
149
    /**
150
     *  Resets the session
151
     */
152
    public static function destroySession()
153
    {
154
        $id = session_id();
155
        if(!empty($id)) {
156
            $_SESSION = array();
157
            session_destroy();
158
            session_start();
159
        }
160
    }
161
162
    /**
163
     * @param $key
164
     * @param $val
165
     */
166
    public static function set($key, $val)
167
    {
168
        $_SESSION[$key] = $val;
169
    }
170
171
    /**
172
     * @param $key
173
     * @return null
174
     */
175
    public static function get($key)
176
    {
177
        return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
178
    }
179
180
    /**
181
     * @param $key
182
     * @param $val
183
     */
184
    public static function destroy($key)
185
    {
186
        unset($_SESSION[$key]);
187
    }
188
}