我正在尝试设置simplesaml。我使用可用的最新版本。但是,当我尝试在其上开始某些操作时,收到以下错误消息:
PHP警告:session_name():当标头已在第72行的C:\ simplesamlphp_sp \ lib \ SimpleSAML \ SessionHandlerPHP.php中发送时,无法更改会话名称 PHP警告:session_id():在第173行的C:\ simplesamlphp_sp \ lib \ SimpleSAML \ SessionHandlerPHP.php中已发送标头时,无法更改会话ID PHP警告:ini_set():标头已发送。您目前无法在第225行的C:\ simplesamlphp_sp \ lib \ SimpleSAML \ SessionHandlerPHP.php中更改会话模块的ini设置 PHP警告:session_id():在第173行的C:\ simplesamlphp_sp \ lib \ SimpleSAML \ SessionHandlerPHP.php中已发送标头时,无法更改会话ID
这是来自simplesaml的SessionHandlerPHP文件
1 <?php
2
3 /**
4 * This file is part of SimpleSAMLphp. See the file COPYING in the root of the distribution for licence information.
5 *
6 * This file defines a session handler which uses the default php session handler for storage.
7 *
8 * @author Olav Morken, UNINETT AS. <andreas.solberg@uninett.no>
9 * @package SimpleSAMLphp
10 */
11
12 namespace SimpleSAML;
13
14 use SimpleSAML\Error\CannotSetCookie;
15 use SimpleSAML\Utils\HTTP;
16
17 class SessionHandlerPHP extends SessionHandler
18 {
19
20 /**
21 * This variable contains the session cookie name.
22 *
23 * @var string
24 */
25 protected $cookie_name;
26
27 /**
28 * An associative array containing the details of a session existing previously to creating or loading one with this
29 * session handler. The keys of the array will be:
30 *
31 * - id: the ID of the session, as returned by session_id().
32 * - name: the name of the session, as returned by session_name().
33 * - cookie_params: the parameters of the session cookie, as returned by session_get_cookie_params().
34 *
35 * @var array
36 */
37 private $previous_session = [];
38
39
40 /**
41 * Initialize the PHP session handling. This constructor is protected because it should only be called from
42 * \SimpleSAML\SessionHandler::createSessionHandler(...).
43 */
44 protected function __construct()
45 {
46 // call the parent constructor in case it should become necessary in the future
47 parent::__construct();
48
49 $config = Configuration::getInstance();
50 $this->cookie_name = $config->getString('session.phpsession.cookiename', null);
51
52 if (session_status() === PHP_SESSION_ACTIVE) {
53 if (session_name() === $this->cookie_name || $this->cookie_name === null) {
54 Logger::warning(
55 'There is already a PHP session with the same name as SimpleSAMLphp\'s session, or the '.
56 "'session.phpsession.cookiename' configuration option is not set. Make sure to set ".
57 "SimpleSAMLphp's cookie name with a value not used by any other applications."
58 );
59 }
60
61 /*
62 * We shouldn't have a session at this point, so it might be an application session. Save the details to
63 * retrieve it later and commit.
64 */
65 $this->previous_session['cookie_params'] = session_get_cookie_params();
66 $this->previous_session['id'] = session_id();
67 $this->previous_session['name'] = session_name();
68 session_write_close();
69 }
70
71 if (!empty($this->cookie_name)) {
72 session_name($this->cookie_name);
73 } else {
74 $this->cookie_name = session_name();
75 }
76
77 $params = $this->getCookieParams();
78
79 if (!headers_sent()) {
80 session_set_cookie_params(
81 $params['lifetime'],
82 $params['path'],
83 $params['domain'],
84 $params['secure'],
85 $params['httponly']
86 );
87 }
88
89 $savepath = $config->getString('session.phpsession.savepath', null);
90 if (!empty($savepath)) {
91 session_save_path($savepath);
92 }
93 }
94
95
96 /**
97 * Restore a previously-existing session.
98 *
99 * Use this method to restore a previous PHP session existing before SimpleSAMLphp initialized its own session.
100 *
101 * WARNING: do not use this method directly, unless you know what you are doing. Calling this method directly,
102 * outside of \SimpleSAML\Session, could cause SimpleSAMLphp's session to be lost or mess the application's one. The
103 * session must always be saved properly before calling this method. If you don't understand what this is about,
104 * don't use this method.
105 */
106 public function restorePrevious()
107 {
108 if (empty($this->previous_session)) {
109 return; // nothing to do here
110 }
111
112 // close our own session
113 session_write_close();
114
115 session_name($this->previous_session['name']);
116 session_set_cookie_params(
117 $this->previous_session['cookie_params']['lifetime'],
118 $this->previous_session['cookie_params']['path'],
119 $this->previous_session['cookie_params']['domain'],
120 $this->previous_session['cookie_params']['secure'],
121 $this->previous_session['cookie_params']['httponly']
122 );
123 session_id($this->previous_session['id']);
124 $this->previous_session = [];
125 @session_start();
126
127 /*
128 * At this point, we have restored a previously-existing session, so we can't continue to use our session here.
129 * Therefore, we need to load our session again in case we need it. We remove this handler from the parent
130 * class so that the handler is initialized again if we ever need to do something with the session.
131 */
132 parent::$sessionHandler = null;
133 }
134
135
136 /**
137 * Create a new session id.
138 *
139 * @return string The new session id.
140 */
141 public function newSessionId()
142 {
143 // generate new (secure) session id
144 if (function_exists('session_create_id')) {
145 $sid_length = (int) ini_get('session.sid_length');
146 $sid_bits_per_char = (int) ini_get('session.sid_bits_per_character');
147
148 if (($sid_length * $sid_bits_per_char) < 128) {
149 \SimpleSAML\Logger::warning("Unsafe defaults used for sessionId generation!");
150 }
151 $sessionId = session_create_id();
152 } else {
153 $sessionId = bin2hex(openssl_random_pseudo_bytes(16));
154 }
155 \SimpleSAML\Session::createSession($sessionId);
156 return $sessionId;
157 }
158
159 /**
160 * Retrieve the session ID saved in the session cookie, if there's one.
161 *
162 * @return string|null The session id saved in the cookie or null if no session cookie was set.
163 *
164 * @throws \SimpleSAML\Error\Exception If the cookie is marked as secure but we are not using HTTPS.
165 */
166 public function getCookieSessionId()
167 {
168 if (!$this->hasSessionCookie()) {
169 return null; // there's no session cookie, can't return ID
170 }
171
172 // do not rely on session_id() as it can return the ID of a previous session. Get it from the cookie instead.
173 session_id($_COOKIE[$this->cookie_name]);
174
175 $session_cookie_params = session_get_cookie_params();
176
177 if ($session_cookie_params['secure'] && !HTTP::isHTTPS()) {
178 throw new \SimpleSAML\Error\Exception('Session start with secure cookie not allowed on http.');
179 }
180
181 @session_start();
182 return session_id();
183 }
184
185
186 /**
187 * Retrieve the session cookie name.
188 *
189 * @return string The session cookie name.
190 */
191 public function getSessionCookieName()
192 {
193 return $this->cookie_name;
194 }
195
196
197 /**
198 * Save the current session to the PHP session array.
199 *
200 * @param \SimpleSAML\Session $session The session object we should save.
201 */
202 public function saveSession(\SimpleSAML\Session $session)
203 {
204 $_SESSION['SimpleSAMLphp_SESSION'] = serialize($session);
205 }
206
207
208 /**
209 * Load the session from the PHP session array.
210 *
211 * @param string|null $sessionId The ID of the session we should load, or null to use the default.
212 *
213 * @return \SimpleSAML\Session|null The session object, or null if it doesn't exist.
214 *
215 * @throws \SimpleSAML\Error\Exception If it wasn't possible to disable session cookies or we are trying to load a
216 * PHP session with a specific identifier and it doesn't match with the current session identifier.
217 */
218 public function loadSession($sessionId = null)
219 {
220 assert(is_string($sessionId) || $sessionId === null);
221
222 if ($sessionId !== null) {
223 if (session_id() === '') {
224 // session not initiated with getCookieSessionId(), start session without setting cookie
225 $ret = ini_set('session.use_cookies', '0');
226 if ($ret === false) {
227 throw new \SimpleSAML\Error\Exception('Disabling PHP option session.use_cookies failed.');
228 }
229
230 session_id($sessionId);
231 @session_start();
232 } elseif ($sessionId !== session_id()) {
233 throw new \SimpleSAML\Error\Exception('Cannot load PHP session with a specific ID.');
234 }
235 } elseif (session_id() === '') {
236 $this->getCookieSessionId();
237 }
238
239 if (!isset($_SESSION['SimpleSAMLphp_SESSION'])) {
240 return null;
241 }
242
243 $session = $_SESSION['SimpleSAMLphp_SESSION'];
244 assert(is_string($session));
245
246 $session = unserialize($session);
247
248 return ($session !== false) ? $session : null;
249 }
250
251
252 /**
253 * Check whether the session cookie is set.
254 *
255 * This function will only return false if is is certain that the cookie isn't set.
256 *
257 * @return boolean True if it was set, false otherwise.
258 */
259 public function hasSessionCookie()
260 {
261 return array_key_exists($this->cookie_name, $_COOKIE);
262 }
263
264
265 /**
266 * Get the cookie parameters that should be used for session cookies.
267 *
268 * This function contains some adjustments from the default to provide backwards-compatibility.
269 *
270 * @return array The cookie parameters for our sessions.
271 * @link http://www.php.net/manual/en/function.session-get-cookie-params.php
272 *
273 * @throws \SimpleSAML\Error\Exception If both 'session.phpsession.limitedpath' and 'session.cookie.path' options
274 * are set at the same time in the configuration.
275 */
276 public function getCookieParams()
277 {
278 $config = Configuration::getInstance();
279
280 $ret = parent::getCookieParams();
281
282 if ($config->hasValue('session.phpsession.limitedpath') && $config->hasValue('session.cookie.path')) {
283 throw new \SimpleSAML\Error\Exception(
284 'You cannot set both the session.phpsession.limitedpath and session.cookie.path options.'
285 );
286 } elseif ($config->hasValue('session.phpsession.limitedpath')) {
287 $ret['path'] = $config->getBoolean(
288 'session.phpsession.limitedpath',
289 false
290 ) ? $config->getBasePath() : '/';
291 }
292
293 $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', true);
294
295 return $ret;
296 }
297
298
299 /**
300 * Set a session cookie.
301 *
302 * @param string $sessionName The name of the session.
303 * @param string|null $sessionID The session ID to use. Set to null to delete the cookie.
304 * @param array|null $cookieParams Additional parameters to use for the session cookie.
305 *
306 * @throws \SimpleSAML\Error\CannotSetCookie If we can't set the cookie.
307 */
308 public function setCookie($sessionName, $sessionID, array $cookieParams = null)
309 {
310 if ($cookieParams === null) {
311 $cookieParams = session_get_cookie_params();
312 }
313
314 if ($cookieParams['secure'] && !HTTP::isHTTPS()) {
315 throw new CannotSetCookie(
316 'Setting secure cookie on plain HTTP is not allowed.',
317 CannotSetCookie::SECURE_COOKIE
318 );
319 }
320
321 if (headers_sent()) {
322 throw new CannotSetCookie(
323 'Headers already sent.',
324 CannotSetCookie::HEADERS_SENT
325 );
326 }
327
328 if (session_id() !== '') {
329 // session already started, close it
330 session_write_close();
331 }
332
333 session_set_cookie_params(
334 $cookieParams['lifetime'],
335 $cookieParams['path'],
336 $cookieParams['domain'],
337 $cookieParams['secure'],
338 $cookieParams['httponly']
339 );
340
341 session_id($sessionID);
342 @session_start();
343 }
344}
345
如何更改文件,这样就不会再出现此错误了?我从这个问题尝试过:
How to fix "Headers already sent" error in PHP
但是它似乎不起作用?也不是我的代码,它是来自simplesaml的代码。
我使用Windows机器(hyper-v)和PHP 7.3.4(NTS版本15),并且它在IIS的本地网页上运行。事实证明,它应该在带有apache服务器的Linux版本上运行。但是我需要让它在带有IIS的Hyper-V上运行。