Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Session;
|
Chris@0
|
4
|
Chris@0
|
5 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
6
|
Chris@0
|
7 /**
|
Chris@0
|
8 * Defines the default session configuration generator.
|
Chris@0
|
9 */
|
Chris@0
|
10 class SessionConfiguration implements SessionConfigurationInterface {
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * An associative array of session ini settings.
|
Chris@0
|
14 */
|
Chris@0
|
15 protected $options;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Constructs a new session configuration instance.
|
Chris@0
|
19 *
|
Chris@0
|
20 * @param array $options
|
Chris@0
|
21 * An associative array of session ini settings.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @see \Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage::__construct()
|
Chris@0
|
24 * @see http://php.net/manual/session.configuration.php
|
Chris@0
|
25 */
|
Chris@0
|
26 public function __construct($options = []) {
|
Chris@0
|
27 $this->options = $options;
|
Chris@0
|
28 }
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * {@inheritdoc}
|
Chris@0
|
32 */
|
Chris@0
|
33 public function hasSession(Request $request) {
|
Chris@0
|
34 return $request->cookies->has($this->getName($request));
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * {@inheritdoc}
|
Chris@0
|
39 */
|
Chris@0
|
40 public function getOptions(Request $request) {
|
Chris@0
|
41 $options = $this->options;
|
Chris@0
|
42
|
Chris@0
|
43 // Generate / validate the cookie domain.
|
Chris@0
|
44 $options['cookie_domain'] = $this->getCookieDomain($request) ?: '';
|
Chris@0
|
45
|
Chris@0
|
46 // If the site is accessed via SSL, ensure that the session cookie is
|
Chris@0
|
47 // issued with the secure flag.
|
Chris@0
|
48 $options['cookie_secure'] = $request->isSecure();
|
Chris@0
|
49
|
Chris@0
|
50 // Set the session cookie name.
|
Chris@0
|
51 $options['name'] = $this->getName($request);
|
Chris@0
|
52
|
Chris@0
|
53 return $options;
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * Returns the session cookie name.
|
Chris@0
|
58 *
|
Chris@0
|
59 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
60 * The request.
|
Chris@0
|
61 *
|
Chris@0
|
62 * @return string
|
Chris@0
|
63 * The name of the session cookie.
|
Chris@0
|
64 */
|
Chris@0
|
65 protected function getName(Request $request) {
|
Chris@0
|
66 // To prevent session cookies from being hijacked, a user can configure the
|
Chris@0
|
67 // SSL version of their website to only transfer session cookies via SSL by
|
Chris@0
|
68 // using PHP's session.cookie_secure setting. The browser will then use two
|
Chris@0
|
69 // separate session cookies for the HTTPS and HTTP versions of the site. So
|
Chris@0
|
70 // we must use different session identifiers for HTTPS and HTTP to prevent a
|
Chris@0
|
71 // cookie collision.
|
Chris@0
|
72 $prefix = $request->isSecure() ? 'SSESS' : 'SESS';
|
Chris@0
|
73 return $prefix . $this->getUnprefixedName($request);
|
Chris@0
|
74 }
|
Chris@0
|
75
|
Chris@0
|
76 /**
|
Chris@0
|
77 * Returns the session cookie name without the secure/insecure prefix.
|
Chris@0
|
78 *
|
Chris@0
|
79 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
80 * The request.
|
Chris@0
|
81 *
|
Chris@0
|
82 * @returns string
|
Chris@0
|
83 * The session name without the prefix (SESS/SSESS).
|
Chris@0
|
84 */
|
Chris@0
|
85 protected function getUnprefixedName(Request $request) {
|
Chris@0
|
86 if ($test_prefix = $this->drupalValidTestUa()) {
|
Chris@0
|
87 $session_name = $test_prefix;
|
Chris@0
|
88 }
|
Chris@0
|
89 elseif (isset($this->options['cookie_domain'])) {
|
Chris@0
|
90 // If the user specifies the cookie domain, also use it for session name.
|
Chris@0
|
91 $session_name = $this->options['cookie_domain'];
|
Chris@0
|
92 }
|
Chris@0
|
93 else {
|
Chris@0
|
94 // Otherwise use $base_url as session name, without the protocol
|
Chris@0
|
95 // to use the same session identifiers across HTTP and HTTPS.
|
Chris@0
|
96 $session_name = $request->getHost() . $request->getBasePath();
|
Chris@0
|
97 // Replace "core" out of session_name so core scripts redirect properly,
|
Chris@0
|
98 // specifically install.php.
|
Chris@0
|
99 $session_name = preg_replace('#/core$#', '', $session_name);
|
Chris@0
|
100 }
|
Chris@0
|
101
|
Chris@0
|
102 return substr(hash('sha256', $session_name), 0, 32);
|
Chris@0
|
103 }
|
Chris@0
|
104
|
Chris@0
|
105 /**
|
Chris@0
|
106 * Return the session cookie domain.
|
Chris@0
|
107 *
|
Chris@0
|
108 * The Set-Cookie response header and its domain attribute are defined in RFC
|
Chris@17
|
109 * 2109, RFC 2965 and RFC 6265 each one superseding the previous version.
|
Chris@0
|
110 *
|
Chris@0
|
111 * @see http://tools.ietf.org/html/rfc2109
|
Chris@0
|
112 * @see http://tools.ietf.org/html/rfc2965
|
Chris@0
|
113 * @see http://tools.ietf.org/html/rfc6265
|
Chris@0
|
114 *
|
Chris@0
|
115 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
116 * The request.
|
Chris@0
|
117 *
|
Chris@0
|
118 * @returns string
|
Chris@0
|
119 * The session cookie domain.
|
Chris@0
|
120 */
|
Chris@0
|
121 protected function getCookieDomain(Request $request) {
|
Chris@0
|
122 if (isset($this->options['cookie_domain'])) {
|
Chris@0
|
123 $cookie_domain = $this->options['cookie_domain'];
|
Chris@0
|
124 }
|
Chris@0
|
125 else {
|
Chris@0
|
126 $host = $request->getHost();
|
Chris@0
|
127 // To maximize compatibility and normalize the behavior across user
|
Chris@0
|
128 // agents, the cookie domain should start with a dot.
|
Chris@0
|
129 $cookie_domain = '.' . $host;
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@0
|
132 // Cookies for domains without an embedded dot will be rejected by user
|
Chris@0
|
133 // agents in order to defeat malicious websites attempting to set cookies
|
Chris@0
|
134 // for top-level domains. Also IP addresses may not be used in the domain
|
Chris@0
|
135 // attribute of a Set-Cookie header.
|
Chris@0
|
136 if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
|
Chris@0
|
137 return $cookie_domain;
|
Chris@0
|
138 }
|
Chris@0
|
139 }
|
Chris@0
|
140
|
Chris@0
|
141 /**
|
Chris@0
|
142 * Wraps drupal_valid_test_ua().
|
Chris@0
|
143 *
|
Chris@0
|
144 * @return string|false
|
Chris@0
|
145 * Either the simpletest prefix (the string "simpletest" followed by any
|
Chris@0
|
146 * number of digits) or FALSE if the user agent does not contain a valid
|
Chris@0
|
147 * HMAC and timestamp.
|
Chris@0
|
148 */
|
Chris@0
|
149 protected function drupalValidTestUa() {
|
Chris@0
|
150 return drupal_valid_test_ua();
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 }
|