if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
$server_port = $_SERVER['SERVER_PORT'];
} else {
$ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
$server_port = $ports[0];
}そして、Alibaba Cloud の SLB はバックエンド サーバーに渡されませんXX -FORWARDED-PORT この http ヘッダーなので、phpCAS は $_SERVER['SERVER_PORT'] を取得します。これは nginx のポート 8080 です。
setFixedServiceURL 関数が用意されています。
phpCAS::setFixedServiceURL($request->url());コールバック アドレスは現在は正常ですが、コールバック アドレスが返されます。チケットが無効であることがクライアントに通知されます。 ログとコードの確認を続けたところ、ここで不注意だったことがわかりました。CAS サーバーがクライアントに戻ったとき、ページの URL は
http://client/login?ticket= でした。 xxxxx, クライアントがチケットを使用してサーバーとユーザー情報を交換する場合、チケットを申請するときにコールバック アドレス (サービス) も取得する必要があります。サーバーはチケットとサービスが一致しているかどうかを確認し、チケットを申請するときのサービスは http:///client/login である必要があるため、URL 内のチケット パラメータを削除する必要があります。
phpCAS::setFixedServiceURL($this->getUrlWithoutTicket($request));
getUrlWithoutTicket 関数は次のとおりです:
private function getUrlWithoutTicket(Request $request)
{
$query = parse_query($request->getQueryString());
unset($query['ticket']);
$question = $request->getBaseUrl().$request->getPathInfo() == '/' ? '/?' : '?';
return $query ? $request->url().$question.http_build_query($query) : $request->url();
}セッションピットこれは、phpCAS Laravel の組み合わせピットです。 。 PHP はデフォルトでセッション ストレージをファイルとして保存するため、単一マシンを複数のマシンに変換するときに非常に重要な点は、セッション共有を処理することです。解決策も非常に簡単で、セッションの保存方法をファイルから redis/memecache/database などに変更するだけです。 Laravel はこれらのドライバーをデフォルトで提供するので、喜んで .env ファイルを変更し、SESSION_DRIVER を redis に変更しました。オンラインで試してみましたが、機能しませんでした。phpCAS によって $_SESSION 変数に加えられた変更は、redis に書き込まれませんでした。何が起こっているのでしょうか。
session_set_save_handler の使用法が想像どおりではないことがわかりました。つまり、Laravel のセッションは実際には php の # を変更していませんでした。 # #$_SESSION の読み取りおよび書き込みロジックについては、$_SESSION を直接操作するか、デフォルトの動作 (ローカル ファイルの読み取りおよび書き込み) に従います。 そうですね、幸いなことに、Laravel のいくつかの SessionDrivers は
インターフェースを実装しています。これを自分たちで session_set_save_handler :<pre class="brush:php;toolbar:false">session_set_save_handler(app(StartSession::class)->getSession($request)->getHandler());</pre>万と呼ぶことができます。エラー!
session_write_close(): Session callback expects true/false return value
Laravel コードを追跡した結果、redis ドライバーの親クラス
Illuminate\Session\CacheBasedSessionHandler の write メソッドが void を返すことがわかりました。 。そこで、それを修正するために PR を送信しましたが、拒否されるとは予想していませんでした。誰かが以前に修正したのに、サーバーが停止する可能性があると言って元に戻したことが判明しました。しかし、私は修正しませんでした。具体的な問題が見つからない。 まあ、memcache と redis は両方ともこの親クラスを継承しているため、代わりにデータベースを試す必要があります。
今回は
session_write_close エラーは報告されませんが、CAS ログインに依然として問題があり、CAS サーバーとコールバック URL の間を飛び続けます。そこで、すべてのログとコードを追跡したところ、データベース ドライバー クラス Illuminate\Session\DatabaseSessionHandler の destroy メソッドが $this->exists## を削除していないことがわかりました。セッションを破棄した後 # 属性は false としてマークされ、phpCAS のロジックは renameSession
$old_session = $_SESSION;
session_destroy();
$session_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $ticket);
session_id($session_id);
session_start();
$_SESSION = $old_session;
結果は $_SESSION = $ old_session; 対応する操作セッション テーブルの SQL は挿入ではなく更新を実行します。これは、セッション データをセッション テーブルに書き込むことができないことを意味します。 実際には、セッション ラッパーを自分で作成して処理する以外に方法はありません。
namespace App\Services;
use SessionHandlerInterface;
class MySession implements SessionHandlerInterface
{
/**
* @var SessionHandlerInterface
*/
protected $realHdl;
/**
* Session constructor.
* @param SessionHandlerInterface $realHdl
*/
public function __construct(SessionHandlerInterface $realHdl)
{
$this->realHdl = $realHdl;
}
public function close()
{
return $this->realHdl->close();
}
public function destroy($session_id)
{
return $this->realHdl->destroy($session_id);
}
public function gc($maxlifetime)
{
return $this->realHdl->gc($maxlifetime);
}
public function open($save_path, $name)
{
return $this->realHdl->open($save_path, $name);
}
public function read($session_id)
{
return $this->realHdl->read($session_id) ?: '';
}
public function write($session_id, $session_data)
{
$this->realHdl->write($session_id, $session_data);
return true; // 这里
}
} そして session_set_save_handler
を呼び出してsession_set_save_handler(new MySession(app(StartSession::class)->getSession($request)->getHandler()));
Done! になります。 

