diff --git a/src/queryyetsimple/bootstrap/option/cookie.php b/src/queryyetsimple/bootstrap/option/cookie.php index 65060ba11..47eecd7b5 100644 --- a/src/queryyetsimple/bootstrap/option/cookie.php +++ b/src/queryyetsimple/bootstrap/option/cookie.php @@ -66,5 +66,17 @@ * 这里的过期时间为我们在当前时间上加上了过期的秒数量即为过期时间 * 相关技术文档:http://php.net/manual/zh/function.setcookie.php */ - 'expire' => 86400 + 'expire' => 86400, + + /** + * --------------------------------------------------------------- + * cookie 仅 HTTP 协议访问 + * --------------------------------------------------------------- + * + * 设置成 TRUE,Cookie 仅可通过 HTTP 协议访问。 这意思就是 Cookie 无法通过类似 JavaScript 这样的脚本语言访问。 + * 要有效减少 XSS 攻击时的身份窃取行为,可建议用此设置(虽然不是所有浏览器都支持),不过这个说法经常有争议。 PHP 5.2.0 中添加。 + * TRUE 或 FALSE + * 相关技术文档:http://php.net/manual/zh/function.setcookie.php + */ + 'httponly' => false ]; diff --git a/src/queryyetsimple/cache/abstracts/cache.php b/src/queryyetsimple/cache/abstracts/cache.php index da7f9a44b..9b0c87eb1 100644 --- a/src/queryyetsimple/cache/abstracts/cache.php +++ b/src/queryyetsimple/cache/abstracts/cache.php @@ -96,7 +96,7 @@ protected function getCacheName($sCacheName, $arrOption) { * @param array $arrOption * @return void */ - protected function initialization($arrOption) { + protected function initialization($arrOption = []) { foreach ( array_keys ( $this->arrClasssFacesOption ) as $strOption ) { $arrTemp = explode ( '.', $strOption ); $arrTemp = array_pop ( $arrTemp ); @@ -106,7 +106,7 @@ protected function initialization($arrOption) { $this->arrOption ['expire'] = $this->arrOption ['cache\expire']; unset ( $this->arrOption ['cache\prefix'], $this->arrOption ['cache\expire'] ); - if (is_array ( $arrOption )) { + if ($arrOption) { $this->arrOption = array_merge ( $this->arrOption, $arrOption ); } } diff --git a/src/queryyetsimple/cache/file.php b/src/queryyetsimple/cache/file.php index 2a26a1e37..5418cde6b 100644 --- a/src/queryyetsimple/cache/file.php +++ b/src/queryyetsimple/cache/file.php @@ -101,7 +101,7 @@ public function get($sCacheName, $mixDefault = false, array $arrOption = []) { } flock ( $hFp, LOCK_SH ); - // 头部的 15 个字节存储了安全代码 + // 头部的 42 个字节存储了安全代码 $nLen = filesize ( $sCachePath ); fread ( $hFp, static::HEADER_LENGTH ); $nLen -= static::HEADER_LENGTH; diff --git a/src/queryyetsimple/cookie/cookie.php b/src/queryyetsimple/cookie/cookie.php index a9486b071..dfb32d8f5 100644 --- a/src/queryyetsimple/cookie/cookie.php +++ b/src/queryyetsimple/cookie/cookie.php @@ -39,15 +39,32 @@ class cookie { 'cookie\prefix' => 'q_', 'cookie\expire' => 86400, 'cookie\domain' => '', - 'cookie\path' => '/' + 'cookie\path' => '/', + 'cookie\httponly' => false ]; + /** + * 缓存配置 + * + * @var array + */ + protected $arrOption = [ ]; + /** * 构造函数 * + * @param array $arrOption * @return void */ - public function __construct() { + public function __construct(array $arrOption = []) { + foreach ( array_keys ( $this->arrClasssFacesOption ) as $strOption ) { + $arrTemp = explode ( '\\', $strOption ); + $arrTemp = array_pop ( $arrTemp ); + $this->arrOption [$arrTemp] = $this->classsFacesOption ( $strOption ); + } + if ($arrOption) { + $this->arrOption = array_merge ( $this->arrOption, $arrOption ); + } } /** @@ -55,95 +72,104 @@ public function __construct() { * * @param string $sName * @param string $mixValue - * @param array $in - * life 过期时间 - * cookie_domain 是否启用域名 - * prefix 是否开启前缀 - * http_only + * @param array $arrOption * @return void */ - public function set($sName, $mixValue = '', array $in = []) { - $in = array_merge ( [ - 'life' => 0, - 'cookie\domain' => null, - 'prefix' => true, - 'http_only' => false - ], $in ); + public function set($sName, $mixValue = '', array $arrOption = []) { + $arrOption = $this->option ( $arrOption, null, false ); // 验证 cookie 值是不是一个标量 assert::notNull ( $mixValue ); assert::scalar ( $mixValue ); - $sName = ($in ['prefix'] === true ? $this->classsFacesOption ( 'cookie\prefix' ) : '') . $sName; + $sName = $arrOption ['prefix'] . $sName; - if ($mixValue === null || $in ['life'] < 0) { - $in ['life'] = - 1; - if (isset ( $_COOKIE [$sName] )) { + if ($mixValue === null || $arrOption ['expire'] < 0) { + if (isset ( $_COOKIE [$sName] )) unset ( $_COOKIE [$sName] ); - } } else { $_COOKIE [$sName] = $mixValue; - if ($in ['life'] !== NULL && $in ['life'] === 0) { - $in ['life'] = $this->classsFacesOption ( 'cookie\expire' ); - } } - $in ['life'] = $in ['life'] > 0 ? time () + $in ['life'] : ($in ['life'] < 0 ? time () - 31536000 : null); - $in ['cookie\domain'] = $in ['cookie\domain'] !== null ? $in ['cookie\domain'] : $this->classsFacesOption ( 'cookie\domain' ); - setcookie ( $sName, $mixValue, $in ['life'], $this->classsFacesOption ( 'cookie\path' ), $in ['cookie\domain'], $_SERVER ['SERVER_PORT'] == 443 ? 1 : 0, $in ['http_only'] ); + $arrOption ['expire'] = $arrOption ['expire'] > 0 ? time () + $arrOption ['expire'] : ($arrOption ['expire'] < 0 ? time () - 31536000 : 0); + setcookie ( $sName, $mixValue, $arrOption ['expire'], $arrOption ['path'], $arrOption ['domain'], ! empty ( $_SERVER ['HTTPS'] ) && strtoupper ( $_SERVER ['HTTPS'] ) == 'ON', $arrOption ['httponly'] ); } /** * 获取 cookie * * @param string $sName - * @param string $bPrefix + * @param mixed $mixDefault + * @param array $arrOption * @return mixed */ - public function get($sName, $bPrefix = true) { - $sName = ($bPrefix ? $this->classsFacesOption ( 'cookie\prefix' ) : '') . $sName; - return isset ( $_COOKIE [$sName] ) ? $_COOKIE [$sName] : null; + public function get($sName, $mixDefault = null, array $arrOption = []) { + $arrOption = $this->option ( $arrOption, null, false ); + $sName = $arrOption ['prefix'] . $sName; + return isset ( $_COOKIE [$sName] ) ? $_COOKIE [$sName] : $mixDefault; } /** * 删除 cookie * * @param string $sName - * @param string $sCookieDomain - * @param boolean $bPrefix + * @param array $arrOption * @return void */ - public function delete($sName, $sCookieDomain = null, $bPrefix = true) { - if (is_null ( $sCookieDomain )) - $sCookieDomain = $this->classsFacesOption ( 'cookie\domain' ); - $this->set ( $sName, null, [ - 'life' => - 1, - 'cookie\domain' => $sCookieDomain, - 'prefix' => $bPrefix - ] ); + public function delete($sName, array $arrOption = []) { + $this->set ( $sName, null, $arrOption ); } /** * 清空 cookie * - * @param boolean $bOnlyDeletePrefix - * @param string $sCookieDomain - * @return cookie 顶层数量 + * @param boolean $bOnlyPrefix + * @param array $arrOption + * @return void */ - public function clear($bOnlyDeletePrefix = true, $sCookieDomain = null) { - $nCookie = count ( $_COOKIE ); - $strCookiePrefix = $this->classsFacesOption ( 'cookie\prefix' ); - if (is_null ( $sCookieDomain )) - $sCookieDomain = $this->classsFacesOption ( 'cookie\domain' ); - foreach ( $_COOKIE as $sKey => $Val ) { - if ($bOnlyDeletePrefix === true && $strCookiePrefix) { - if (strpos ( $sKey, $strCookiePrefix ) === 0) { - $this->delete ( $sKey, $sCookieDomain, false ); + public function clear($bOnlyPrefix = true, array $arrOption = []) { + $arrOption = $this->option ( $arrOption, null, false ); + $strPrefix = $arrOption ['prefix']; + foreach ( $_COOKIE as $sKey => $mixVal ) { + if ($bOnlyPrefix === true && $strPrefix) { + if (strpos ( $sKey, $strPrefix ) === 0) { + $this->delete ( $sKey, $arrOption ); } } else { - $this->delete ( $sKey, $sCookieDomain, false ); + $arrOption ['prefix'] = ''; + $this->delete ( $sKey, $arrOption ); } } - return $nCookie; + } + + /** + * 修改配置 + * + * @param mixed $mixName + * @param mixed $mixValue + * @param boolean $booMerge + * @return array + */ + public function option($mixName = '', $mixValue = null, $booMerge = true) { + $arrOption = $this->arrOption; + if (! empty ( $mixName )) { + if (is_array ( $mixName )) { + $arrOption = array_merge ( $arrOption, $mixName ); + } else { + if (is_null ( $mixValue )) { + if (isset ( $arrOption [$mixName] )) { + unset ( $arrOption [$mixName] ); + } + } else { + $arrOption [$mixName] = $mixValue; + } + } + + if ($booMerge === true) { + $this->arrOption = $arrOption; + } + } + + return $arrOption; } }