正确的使用方式“记住我” PHP中的功能 [英] Proper way to use "Remember me" functionality in PHP

查看:128
本文介绍了正确的使用方式“记住我” PHP中的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



使用登录系统并尝试实现记住我的功能。



最近,我做了关于这个主题的研究,阅读一堆文章,帖子,故事,小说,童话(称为他们,因为有些不包含甚至一行代码,只是负载的字)约,cookie漏洞,如固定,劫持等。



并决定实现以下目标


  1. 设置登录尝试之间的时间延迟(防止暴力攻击)和限制尝试次数

  2. id on几乎每个操作

我真的很困惑我的主要问题: 记住我功能?使用cookies /会话/数据库?





详细



目前,我的代码看起来像



登录期间我使用以下函数来设置Cookie session

  protected function validateUser($ userid,$ ckey = 0,$ rememmber = 0){
session_start ;
session_regenerate_id(true); //这是一个安全措施
$ _SESSION ['user_id'] = $ userid;
$ _SESSION ['HTTP_USER_AGENT'] = md5($ _ SERVER ['HTTP_USER_AGENT']);
if(isset($ remember)&& $ rememmber =='on'){
setcookie(user_id,$ _SESSION ['user_id'],time()+ 60 * 60 * 24 * COOKIE_TIME_OUT,/);
setcookie(user_key,sha1($ ckey),time()+ 60 * 60 * 24 * COOKIE_TIME_OUT,/);
}
return true;
}

然后在安全用户页面上检查 user_id 使用user_id从db获取有关用户的所有重要数据

  public function protect(){
session_start();

/ *通过检查用户代理来保护会话劫持* /
if(isset($ _ SESSION ['HTTP_USER_AGENT'])){
if($ _SESSION ['HTTP_USER_AGENT' ]!= md5($ _ SERVER ['HTTP_USER_AGENT'])){
$ this-> signout();
exit;
}
}

//在我们允许会话之前,我们需要检查身份验证密钥 - ckey和ctime存储在数据库

/ *如果会话未设置,检查通过记住我设置的cookie * /
if(!isset($ _ SESSION ['user_id'])){
if(isset($ _ COOKIE ['user_id'])&& ; isset($ _COOKIE ['user_key'])){
/ *我们双重检查cookie到期时间是否存储在数据库* /

$ cookie_user_id = $ _COOKIE ['user_id'];
$ stmt = $ this-> db-> prepare(select`ckey`,`ctime` from` users` where`id` =?)或die($ this-> db-> ;错误);
$ stmt-> bind_param(i,$ cookie_user_id)或die(htmlspecialchars($ stmt-> error));
$ stmt-> execute()或die(htmlspecialchars($ stmt-> error));
$ stmt-> bind_result($ ckey,$ ctime)或die($ stmt-> error);
$ stmt-> close()或die(htmlspecialchars($ stmt-> error));
// coookie expiry
if((time() - $ ctime)> 60 * 60 * 24 * COOKIE_TIME_OUT){
$ this-> signout
}
/ *安全检查与不受信任的cookie - 不信任值存储在cookie。
/ *我们还对登录过程中存储在数据库中的cookie匹配中存储的`ckey`进行认证检查* /

if(!empty($ ckey)&& is_numeric $ _COOKIE ['user_id'])&& $ _COOKIE ['key'] == sha1($ ckey)){
session_regenerate_id(); //针对会话固定攻击。

$ _SESSION ['user_id'] = $ _COOKIE ['user_id'];
$ _SESSION ['HTTP_USER_AGENT'] = md5($ _ SERVER ['HTTP_USER_AGENT']);
} else {
$ this-> signout();
}
} else {
if($ page!='main'){
header('Location:'。wsurl);
exit();
}
}
}


解决方案>


但我真的很困惑我的主要问题:哪种方式是适当的,为记住我功能?要使用Cookie /会话/数据库?


Http是一个无状态协议。认证令牌必须持续保持状态。
正确的方法是使用会话。现在你如何跟踪会话?随你便。



在会话中,您可以保存从浏览器不同标准(用户代理,操作系统,屏幕分辨率等)创建的哈希值,以检查令牌是否从同一个环境。你保存越多的标准越难以劫持。 Btw你需要JavaScript来获取每次额外的信息。


Short

Working on login system and trying to implement remember me feature.

Recently, l did research about this subject, read bunch of articles, posts, stories, novels, fairy tales (calling them so, because some of them doesn't contain even 1 line of code, just loads of words) about, cookie vulnerabilities such as fixation, hijacking ... etc.

And decided to achieve following targets

  1. To set time delay between login attempts (to prevent bruteforce attacks) and to limit attempts count
  2. To regenerate session id on nearly every operation

But I really confused about my main problem: which way is proper, for "remember me" feature? to use cookies/session/database?

And please explain your idea on code.(I can't understand clearly without code)

Detailed

Currently, my code looks like that

During sign-in I'm using following function to set cookies and session

protected function validateUser($userid, $ckey=0, $rememmber=0) {
    session_start();
    session_regenerate_id(true); //this is a security measure
    $_SESSION['user_id'] = $userid;
    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
    if (isset($remember) && $rememmber == 'on') {
        setcookie("user_id", $_SESSION['user_id'], time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
        setcookie("user_key", sha1($ckey), time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
    }
    return true;
}

Then on secure user pages, checking for user_id using user_id to fetch all important data about user from db

public function protect() {
        session_start();

        /* Secure against Session Hijacking by checking user agent */
        if (isset($_SESSION['HTTP_USER_AGENT'])) {
            if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {
                $this->signout();
                exit;
            }
        }

// before we allow sessions, we need to check authentication key - ckey and ctime stored in database

        /* If session not set, check for cookies set by Remember me */
        if (!isset($_SESSION['user_id'])) {
            if (isset($_COOKIE['user_id']) && isset($_COOKIE['user_key'])) {
                /* we double check cookie expiry time against stored in database */

                $cookie_user_id = $_COOKIE['user_id'];
                               $stmt = $this->db->prepare("select `ckey`,`ctime` from `users` where `id` =?") or die($this->db->error);
            $stmt->bind_param("i", $cookie_user_id) or die(htmlspecialchars($stmt->error));
            $stmt->execute() or die(htmlspecialchars($stmt->error));
            $stmt->bind_result($ckey, $ctime) or die($stmt->error);
            $stmt->close() or die(htmlspecialchars($stmt->error));
                // coookie expiry
                if ((time() - $ctime) > 60 * 60 * 24 * COOKIE_TIME_OUT) {
                    $this->signout();
                }
                /* Security check with untrusted cookies - dont trust value stored in cookie.       
                  /* We also do authentication check of the `ckey` stored in cookie matches that stored in database during login */

                if (!empty($ckey) && is_numeric($_COOKIE['user_id']) && $_COOKIE['key'] == sha1($ckey)) {
                    session_regenerate_id(); //against session fixation attacks.

                    $_SESSION['user_id'] = $_COOKIE['user_id'];
                    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
                } else {
                    $this->signout();
                }
            } else {
                if ($page != 'main') {
                    header('Location:' . wsurl);
                    exit();
                }
            }
        }

解决方案

But I really confused about my main problem: which way is proper, for "remember me" feature? to use cookies/session/database?

Http is a stateless protocall. Authentication token must persist to keep the state. Proper way is to use session. Now how do you track the session? It's up to you. But cookies are not bad.

In the session you can save a hash created from browser different criteria(user agent, os, screen resolution etc) to check if the token is from same environment. The more criteria you save the more itll be harder to hijack. Btw you need JavaScript to grab ths extra information every time.

这篇关于正确的使用方式“记住我” PHP中的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆