Passport.class.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. namespace Cas\Module;
  3. use KIF\Exception\ParamsException;
  4. use KIF\Core\Config;
  5. use KIF\Data\ResultWrapper;
  6. use KIF\Core\Request;
  7. use KIF\Verify;
  8. /**
  9. *
  10. * 用户通行证
  11. * @author lishumingoo@gmail.com
  12. */
  13. class Passport {
  14. /**
  15. * 安全key
  16. * @var string
  17. */
  18. private $securityKey;
  19. private $login_cookie_name = 'TM_PASSPORT_MEMBER';
  20. /**
  21. * 登陆类型之:未授权
  22. * @var unknown
  23. */
  24. const LOGIN_TYPE_NOT_AUTH = '1';
  25. /**
  26. * 登陆类型之:已授权
  27. * @var unknown
  28. */
  29. const LOGIN_TYPE_HAS_AUTH = '2';
  30. public function __construct() {
  31. $PASSPORT_SIGN_KEY = Config::getInstance()->get('passport_sign_key');
  32. if (!$PASSPORT_SIGN_KEY) {
  33. throw new ParamsException('请指定securityKey');
  34. }
  35. $this->securityKey = $PASSPORT_SIGN_KEY;
  36. }
  37. /**
  38. * 登陆
  39. */
  40. public function login() {}
  41. /**
  42. * 注册
  43. * @param array $info
  44. */
  45. public function register(array $info) {}
  46. /**
  47. * 获取登录用户信息
  48. * @return ResultWrapper 成功:存在登录cookie里的信息作为数组返回;失败:失败原因
  49. */
  50. public function getLoginInfo() {
  51. if (!isset($_COOKIE[$this->login_cookie_name])) {
  52. return ResultWrapper::fail('没有登录cookie');
  53. }
  54. $loginCookie = $_COOKIE[$this->login_cookie_name];
  55. $loginInfo = array();
  56. parse_str($loginCookie, $loginInfo);
  57. $tmpResult = $this->verifySign($loginInfo);
  58. if (!$tmpResult->isSuccess()) {
  59. return $tmpResult;
  60. }
  61. return ResultWrapper::success($loginInfo);
  62. }
  63. /**
  64. * 写登录信息到cookie
  65. * @param array $info
  66. * @return ResultWrapper
  67. */
  68. public function writeLoginCookie(array $info) {
  69. if (is_null($info['expire'])) {// 说明这是个当前会话期有效的登录用户
  70. $info['expire'] = time() + 4 * 60 * 60;//登录cookie签名的有效性,设为4小时
  71. $cookie_expire = null;//让登录cookie在当前会话期有效
  72. } else {
  73. # 让登录cookie的存在期比 登录cookie签名有效性多1天。避免用户电脑时间与服务器时间不一致,导致签名在有效期,但cookie却已失效的情况。
  74. // $cookie_expire = $info['expire'] + 24 * 60 * 60;
  75. $cookie_expire = $info['expire'];
  76. }
  77. if (is_null($info['timestamp'])) {//
  78. $info['timestamp'] = time();
  79. }
  80. # 版本号,为以后安全性升级做准备
  81. $info['version'] = '0.1';
  82. $tmpResult = $this->sign($info);
  83. if (!$tmpResult->isSuccess()) {//签名失败
  84. return $tmpResult;
  85. }
  86. $info['sign'] = $tmpResult->getData();
  87. setcookie($this->login_cookie_name, http_build_query($info), $cookie_expire, '/', Request::rootDomain());
  88. return ResultWrapper::success();
  89. }
  90. /**
  91. * 对 $info 做签名
  92. *
  93. * @param array $info 格式:array
  94. * (
  95. * // 这些是必要字段
  96. * 'uid' => (int),//用户id
  97. * 'uname' => (string),//用户名
  98. * 'expire' => (int),//签名有效期,过了这个有效期,即使签名正确,也不认。
  99. * 'register_type' => (int),//用户注册类型
  100. * )
  101. *
  102. * @return ResultWrapper 成功:返回签名$sign;失败:返回失败原因
  103. */
  104. public function sign(array $info) {
  105. if (!isset($info['uid']) || !Verify::int($info['uid'])) {
  106. return ResultWrapper::fail('无效的uid');
  107. }
  108. if (!isset($info['expire']) || !Verify::int($info['expire'])) {
  109. return ResultWrapper::fail('无效的expire');
  110. }
  111. // if (!isset($info['nickname']) || !is_string($info['nickname']) || empty($info['nickname'])) {
  112. // return ResultWrapper::fail('无效的uname');
  113. // }
  114. ksort($info);
  115. $tmpStr = '';
  116. foreach ($info as $k => $v) {
  117. if ($v != '' && $k != 'sign') {
  118. $tmpStr .= "{$k}={$v}&";
  119. }
  120. }
  121. $tmpStr .= "securityKey={$this->securityKey}";
  122. $sign = strtolower(sha1($tmpStr));
  123. return ResultWrapper::success($sign);
  124. }
  125. /**
  126. * 验证 $info 的有效性
  127. * @param array $info
  128. * @return ResultWrapper
  129. */
  130. public function verifySign(array $info) {
  131. if (!isset($info['sign'])) {
  132. return ResultWrapper::fail('没有指定sign值,无法校验');
  133. }
  134. $tmpResult = $this->sign($info);
  135. if (!$tmpResult->isSuccess()) {
  136. return $tmpResult;
  137. }
  138. $sign = $tmpResult->getData();
  139. if ($sign != $info['sign']) {
  140. return ResultWrapper::fail("给定的sign:{$info['sign']} 与 计算后的sign:{$sign} 不等");
  141. }
  142. if ($info['expire'] < time()) {
  143. return ResultWrapper::fail('expire存储的签名有效期已过');
  144. }
  145. return ResultWrapper::success();
  146. }
  147. }