PHP笔记-随机生成cookie、后台检索、通过session获取ID增强安全性

x33g5p2x  于2022-03-07 转载在 其他  
字(4.5k)|赞(0)|评价(0)|浏览(389)

PHP笔记-用户登录&权限拦截说明

这篇博文中设置Cookie时用的是数据库的用户id。这样有问题,用户可以随意改动ID,从而获取不同的用户权限。

这里我们更新下,增加点安全性。构造safe包

内容如下:

CookieAndSession.php

  1. <?php
  2. namespace safe;
  3. class CookieAndSession{
  4. public $cookie;
  5. public $userId;
  6. public $browser;
  7. public $os;
  8. public $timeToLive;
  9. }

CookieTool.php

  1. <?php
  2. namespace safe;
  3. class CookieTool{
  4. protected function generateKey(): string{
  5. $length = 32;
  6. $retKey = "";
  7. for ($i = 0; $i < $length; $i++)
  8. {
  9. $retKey .= chr(mt_rand(33, 126));
  10. }
  11. return $retKey;
  12. }
  13. protected function getIPAddress(): string{
  14. $ipaddress = "";
  15. if (isset($_SERVER['HTTP_CLIENT_IP']))
  16. $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
  17. else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
  18. $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
  19. else if(isset($_SERVER['HTTP_X_FORWARDED']))
  20. $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
  21. else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
  22. $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
  23. else if(isset($_SERVER['HTTP_FORWARDED']))
  24. $ipaddress = $_SERVER['HTTP_FORWARDED'];
  25. else if(isset($_SERVER['REMOTE_ADDR']))
  26. $ipaddress = $_SERVER['REMOTE_ADDR'];
  27. else
  28. $ipaddress = 'UNKNOWN';
  29. return $ipaddress;
  30. }
  31. protected function getBrowser($agent): string{
  32. $browserAgent = "";
  33. if(strstr($agent, 'MSIE')) {
  34. $browserAgent="Internet Explorer";
  35. }
  36. else if(strstr($agent, 'Opera')) {
  37. $browserAgent="Opera";
  38. }
  39. else if(strstr($agent, 'Firefox')) {
  40. $browserAgent="Firefox";
  41. }
  42. else if(strstr($agent, 'Chrome')) {
  43. $browserAgent = "Chrome";
  44. }
  45. else if(strstr($agent, 'Safari')) {
  46. $browserAgent = "Safari";
  47. }
  48. else{
  49. $browserAgent = "unknown";
  50. }
  51. return $browserAgent;
  52. }
  53. protected function getPlatform($agent): string{
  54. $agent = strtolower($agent);
  55. $platform = "";
  56. if(strstr($agent, 'win')) {
  57. $platform="windows";
  58. }
  59. else if(strstr($agent, 'linux')) {
  60. $platform = "linux";
  61. }
  62. else{
  63. $platform = "unknown";
  64. }
  65. return $platform;
  66. }
  67. protected function getMacAddress(): string{
  68. $MAC = exec('getmac');
  69. print_r($MAC);
  70. $MAC = strtok($MAC, ' ');
  71. return $MAC;
  72. }
  73. public function printCookieArray(){
  74. global $cookieAndSessionArray;
  75. print_r($cookieAndSessionArray);
  76. }
  77. public function setCookieByUserId($userId){
  78. $userToken = $this->generateKey();
  79. $browserAgent = $this->getBrowser($_SERVER['HTTP_USER_AGENT']);
  80. $platform = $this->getPlatform($_SERVER['HTTP_USER_AGENT']);
  81. $cookieAndSession = new CookieAndSession();
  82. $cookieAndSession->cookie = $userToken;
  83. $cookieAndSession->userId = $userId;
  84. $cookieAndSession->browser = $browserAgent;
  85. $cookieAndSession->os = $platform;
  86. $cookieAndSession->timeToLive = 24 * 60 * 60;
  87. @session_start();
  88. $_SESSION["user"] = serialize($cookieAndSession);
  89. setcookie('userToken',$userToken ,time() + 1 * 24 * 3600);
  90. }
  91. }

因为这里我用的是自定义MVC框架,在每次加载的时候,会调用如下start函数:

  1. public static function start(){
  2. self::setPath();
  3. self::setConfig();
  4. self::setSafe();
  5. self::setUrl();
  6. self::setAutoLoad();
  7. self::setDispatch();
  8. }

其中setSafe()就是新加的,作用是加载对应的php文件

  1. private static function setSafe(){
  2. $files = self::getAllFile(SAFE_PATH);
  3. foreach($files as $file){
  4. if(file_exists($file)){
  5. include $file;
  6. }
  7. }
  8. }

其中getAllfile是获取当前目录下的所有文件,如下:

  1. private static function getAllFile($dir): array{
  2. $retArray = array();
  3. if(!is_dir($dir))
  4. return $retArray;
  5. $files = scandir($dir);
  6. foreach ($files as $file){
  7. $tmpFile = $dir . "/" . $file;
  8. if(!is_dir($tmpFile)){
  9. array_push($retArray, $dir . "/" . $file);
  10. }
  11. }
  12. return $retArray;
  13. }

其中SAFE_PATH如下:

ROOT_PATH在index.php中定义的,如下:

index.php

  1. <?php
  2. define("ROOT_PATH", str_replace("\\", "/", dirname(__DIR__)) . "/");
  3. include ROOT_PATH . "core/App.php";
  4. \core\App::start();

当用户点击登录后:

其userToken就为随机数了

后台登录校验是这样的:

  1. public function check(){
  2. $useName = trim($_POST["userName"]);
  3. $password = trim($_POST["password"]);
  4. $captcha = trim($_POST["captcha"]);
  5. ......
  6. ......
  7. ......
  8. $cookieTool = new CookieTool();
  9. $cookieTool->setCookieByUserId($user['user_id']);
  10. $this->success("登录成功", '', 'dashboard', "index");
  11. }

权限拦截如下:

  1. public function __construct(){
  2. include VENDOR_PATH . "smarty/Smarty.class.php";
  3. $this->smarty = new \Smarty();
  4. $this->smarty->template_dir = APP_PATH . P . "/view/";
  5. $this->smarty->compile_dir = RESOURCES_PATH . "views";
  6. if(strtolower(C) != "privilege"){
  7. if(isset($_COOKIE['userToken'])){
  8. @session_start();
  9. $obj = unserialize($_SESSION["user"]);
  10. if(strcmp($_COOKIE['userToken'], $obj->cookie) != 0){
  11. $this->error("未登录,请先登录", "user", "privilege", "login");
  12. }
  13. $userModel = new UserModel();
  14. $user = $userModel->getById((int)$obj->userId);
  15. if($user){
  16. return;
  17. }
  18. }
  19. $this->error("未登录,请先登录", "user", "privilege", "login");
  20. }
  21. }

相关文章