PHP和SimpleSAML-已发送标题时,无法更改会话名称

时间:2019-04-10 14:01:03

标签: php iis session-cookies hyper-v simplesamlphp

我正在尝试设置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上运行。

0 个答案:

没有答案