Instantly share code, notes, and snippets.
Last active
June 3, 2016 12:53
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save xuecan/2b1cd080ebedd2b6b6ec684e8b77c7d0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @copyright Copyright (c) 2016, 北京联宇益通科技发展有限公司 | |
| */ | |
| namespace Netpas\Common\SessionHandler; | |
| use SessionHandlerInterface; | |
| use Netpas\Exception\Exception; | |
| /** | |
| * 使用 $_COOKIE 和 setcookie() 实现的 Session 处理器。 | |
| * | |
| * @author Xue Can <xuecan@netpas.co> | |
| */ | |
| class CookieSessionHandler implements SessionHandlerInterface | |
| { | |
| /** @var string 加密算法 */ | |
| protected $cipherMethod = ''; | |
| /** @var int 加密算法需要的 IV 长度 */ | |
| protected $ivLength = 0; | |
| /** @var string 密码,为空则使用 Session ID 作为密码 */ | |
| protected $password = ''; | |
| /** @var string 保存数据的 Cookie 名称 */ | |
| protected $cookieName = ''; | |
| /** | |
| * 构造方法。 | |
| * | |
| * @param string $password 密码。 | |
| * @param string $cipherMethod 加密算法。默认为 `AES-256-CBC`。使用 `openssl_get_cipher_methods()` | |
| * 了解可用的加密算法。 | |
| */ | |
| public function __construct($password, $cipherMethod = 'AES-256-CBC') | |
| { | |
| $password = strval($password); | |
| $cipherMethod = strval($cipherMethod); | |
| if ('' === $password) { | |
| $msg = 'Cipher password should not be empty'; | |
| throw new Exception($msg); | |
| } | |
| $this->password = strval($password); | |
| $this->ivLength = openssl_cipher_iv_length($cipherMethod); | |
| if (false === $this->ivLength) { | |
| $msg = sprintf('Unknown cipher algorithm "%s"', $cipherMethod); | |
| throw new Exception($msg); | |
| } | |
| $this->cipherMethod = $cipherMethod; | |
| $cookieName = session_name(); | |
| if ('ID' === strtoupper(substr($cookieName, -2))) { | |
| $cookieName = substr($cookieName, 0, strlen($cookieName) - 2); | |
| } | |
| $cookieName = $cookieName.'DATA'; | |
| $this->cookieName = $cookieName; | |
| } | |
| /** | |
| * 读取 Session 数据。 | |
| * | |
| * @param string $sessionId Session 标识。 | |
| * | |
| * @return string Session 数据,如果无法获取必要的数据,则返回空字符串。 | |
| */ | |
| public function read($sessionId) | |
| { | |
| $password = $this->password; | |
| $iv = substr($sessionId, 0, $this->ivLength); | |
| $raw = $_COOKIE[$this->cookieName] ?? ''; | |
| if (empty($raw)) { | |
| return ''; | |
| } | |
| $parts = explode('|', $raw); | |
| if (2 != count($parts)) { | |
| return ''; | |
| } | |
| $encrypted = base64_decode($parts[0]); | |
| $digest = $parts[1]; | |
| $cipherMethod = $this->cipherMethod; | |
| $data = openssl_decrypt($encrypted, $cipherMethod, $password, 0, $iv); | |
| if ($digest !== hash('sha256', $data)) { | |
| return ''; | |
| } | |
| return $data; | |
| } | |
| /** | |
| * 写入 Session 数据。 | |
| * | |
| * @param string $sessionId Session 标识。 | |
| * @param string $data 要写入的数据。 | |
| * | |
| * @return bool 成功返回 `true`,失败返回 `false`。 | |
| */ | |
| public function write($sessionId, $data) | |
| { | |
| $cookieName = $this->cookieName; | |
| $digest = hash('sha256', $data); | |
| $cipherMethod = $this->cipherMethod; | |
| $password = $this->password; | |
| $iv = substr($sessionId, 0, $this->ivLength); | |
| $encrypted = openssl_encrypt($data, $cipherMethod, $password, 0, $iv); | |
| $raw = base64_encode($encrypted).'|'.$digest; | |
| $params = session_get_cookie_params(); | |
| $expire = time() + $params['lifetime']; | |
| $path = $params['path']; | |
| $domain = $params['domain']; | |
| $secure = $params['secure']; | |
| $httponly = $params['httponly']; | |
| return setcookie($cookieName, $raw, $expire, $path, $domain, $secure, $httponly); | |
| } | |
| /** | |
| * 销毁 Session 记录。 | |
| * | |
| * @param string $sessionId Session 标识。 | |
| * | |
| * @return bool 成功返回 `true`,失败返回 `false`。 | |
| */ | |
| public function destroy($sessionId) | |
| { | |
| $cookieName = $this->cookieName; | |
| $params = session_get_cookie_params(); | |
| $expire = 864000; | |
| $path = $params['path']; | |
| $domain = $params['domain']; | |
| $secure = $params['secure']; | |
| $httponly = $params['httponly']; | |
| return setcookie($cookieName, '', $expire, $path, $domain, $secure, $httponly); | |
| } | |
| /** | |
| * 初始化 Session 机制。 | |
| * | |
| * @param string $savePath 接口需要的参数。 | |
| * @param string $sessionName 接口需要的参数。 | |
| * | |
| * @return bool 总是返回 `true`。 | |
| */ | |
| public function open($savePath, $sessionName) | |
| { | |
| return true; | |
| } | |
| /** | |
| * 关闭 Session。 | |
| * | |
| * @return bool 总是返回 `true`。 | |
| */ | |
| public function close() | |
| { | |
| return true; | |
| } | |
| /** | |
| * 清除过期的 Session 记录。 | |
| * | |
| * @param int $maxlifetime 接口需要的参数。 | |
| * | |
| * @return bool 总是返回 `true`。 | |
| */ | |
| public function gc($maxlifetime) | |
| { | |
| return true; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment