使用COOKIE实现登录 VS 使用SESSION实现登录

摘要:
您可以确定用户是否已登录。PhpclassLogin{//Login publicfunctionlogin{$model=newModel();$pwd=md5;$userInfo=$model-˃db-˃getOne(array('username'=˃$username,'password‘=˃$pwd);if($userInfo){$_SESSION['account'〕=$userInfo;returntrue;}else{returnfalse;}//验证登录publicstaticfunctionisLogin(){if(isset($_SESSION['account‘]){retrntrue;}?如果用户的SESSION信息不存在,则表示用户尚未登录,将跳转到登录页面。

注:本文使用的代码基于PHP,其他语言逻辑同理。

一:使用COOKIE实现登录验证

使用cookie实现登录的方式,主要通过一些单向的加密信息进行验证。比如admin用户登录了之后,服务端生成一个cookie值:admin_1533006028_ bbf2c2b1ec5cfb62d0a30438d8d0305c ,这个cookie值包含用户名,cookie到期时间和一个信息签名。签名的信息为 ”用户名_用户密码_cookie到期时间_盐” 比如:md5(”admin_1533006028_123456_salt123”)。这样用户每次访问,只要获取到这个cookie值,然后验证cookie到期时间和签名。就可以判断该用户是否已登录。

首先看看下面cookie登录的实例代码:

<?php
class Login { //登录 public function login($account,$password) { $lifetime = time()+3600; $model = new Model(); $pwd = md5($password); $userInfo = $model->db->getOne(array(‘username’=>$username,’password’=>$pwd); if($userInfo){ $cookie =$this->user2cookie($userInfo, $lifetime); setcookie('account', $cookie, $lifetime); return true; }else{ return false; } } //验证登录 public static function isLogin() { $cookie = $_COOKIE['account']; $re = $this->cookie2user($cookie); return $re; } //根据cookie判断一个用户是否合法的登录用户 public function cookie2user($cookie) { if(empty($cookie)) return false; list($username,$lifetime,$token) = explode('_',$cookie); //cookie过期或者cookie1分钟内过期 if($lifetime < (time()+60)) return false; $model = new Model(); //获取缓存中的用户信息 $userInfo = $model->redis->get($username); if(!$userInfo){ $userInfo = $model->db->getOne(array(‘username’=>$username)); }else{ $userInfo = parse_url($userInfo); } if(!$userInfo){ return false; } //验证token值 $str = $username.$userInfo['password'].$lifetime.$userInfo[‘salt’]; if($token !== md5($str)) return false; $val = http_build_query($userInfo , '' , '&'); //将用户信息设置到缓存中,键值生命周期为1小时。 $model->redis->set($username,$val,3600); return true; } //生成验证用户登录的cookie值 public function user2cookie($user,$lifetime) { $str = $user['username'].$user['password'].$lifetime.$user[‘salt’]; $token = md5($str); $re = $user['username'].'_'.$lifetime.'_'.$token; return $re; } } ?>

cookie的登录流程: 首先通过Login() 函数验证用户提交的用户名和密码,如果验证通过则将相关信息写入cookie, 后面使用isLogin() 函数对用户的每次访问进行验证,验证的方式也是通过该用户的cookie。验证通过则说明该用户已经登录,否则说明该用户没有登录。跳转到登录页面。

这里重点讲下Login类的两个关键函数cookie2user和user2cookie:

1、  cookie2user根据cookie判断一个用户是否合法的登录用户,即用户每次访问,都会通过isLogin函数验证该用户是否已经登录。验证方式就是获取到用户此次访问的cookie值,然后将验证cookie值里的token(签名信息)值。验证通过,说明该用户是已经登录的,否则就是为登录或者不存在该用户。

2、  user2cookie用于生成验证用户登录的cookie值。如前文所述,该cookie值包含用户名、cookie生存时间和token值。这里关键就是这个token值的生成方式,要注意判断登录的时候生成token值的方式要与此函数生成token值的方式一致。比如这里是将用户名,用户密码,cookie生存时间和盐进行连接并取md5值。当然加密方法也可以不用md5,也可以使用sha1等。

二、使用SESSION实现登录验证

由于session的信息是保留在服务端的,所以用户登录户的信息保存在服务,所以无需像cookie登录的那样将信息进行单向加密。

session登录的示例代码:

<?php

class Login
{
   //登录
   public function  login($account,$password)
   {
        $model = new Model();
        $pwd = md5($password);
        $userInfo = $model->db->getOne(array(‘username’=>$username,’password’=>$pwd);
        if($userInfo){
           $_SESSION[‘account’] = $userInfo;
           return true;
        }else{
            return false;
        }
    }

 
    //验证登录
    public static function isLogin()
    {
         if(isset($_SESSION['account'])){
                return true;
         }else{
                return false;
         }
    }

}

?>    

session的登录流程:首先用户提交的用户名和密码提交到Login() 方法进行验证,如果验证通过则将信息写入session,后面每次访问都会去取该用户的session信息。如果不存在该用户的SESSION信息,则说明该用户还没有登录,跳转到登录页面。已经登录了的用户每次访问,都会通过isLogin() 函数进行验证。验证不通过说明登录过期或者没有登录,则跳转到登录页面。

两种方式都是通过isLogin() 方法来验证用户是否已经登陆的了。该方法一般在程序的入口处进行Login::isLogin() 调用,从而对所有的访问进行验证。

三、两种方式的异同点

除了上文已经简述的之外,这里先介绍下PHP里面处理SESSION的机制。

PHP在调用seesion_start() 函数之后会生成一个字符串(一般是某些不重复的哈希值)。这个字符串就是session_id,当然这个值也可以自行调用函数session_id(‘指定的session_id 值’)进行构建,需要注意的是,session_id()函数必须在session_start() 函数之前先调用。只有调用了session_start() 函数,才会产生相应的session文件和cookie值。

具体过程如下:

1、客户端(浏览器)首次访问时,这里默认开启了session_start() 函数的,此时PHP会随机生成一个不重复的cookie(即session_id,这里假如生成ug9gch0ns7nql4gjoe3jckdab2)值。

 

2、服务端会生成一个session文件默认文件名为’SESS_’.session_id,即:SESS_ ug9gch0ns7nql4gjoe3jckdab2 文件。文件的保存路径默认在php.ini的session.save_path设置的路径中,例如linux系统中默认为/var/lib/php/sessions目录。(注意:此时SESS_ ug9gch0ns7nql4gjoe3jckdab2文件是个空文件,因为服务端还没有信息存入SESSION中,具体看第4步)

 

3、然后将生成的 ug9gch0ns7nql4gjoe3jckdab2 设置到cookie里,cookie键名默认是php.ini里设置的session.name配置项,默认是:session.name=PHPSESSID;相当于执行了$_COOKIE[‘PHPSESSID’]= ug9gch0ns7nql4gjoe3jckdab2;用户此次访问的http响应头部信息里就会包含:

Set-Cookie: PHPSESSID=ug9gch0ns7nql4gjoe3jckdab2; path=/

相应的cookie信息就会保存到客户端。

 

4、用户在登录界面输入用户名和密码并提交。此时浏览器会将用户名和密码和cookie值等信息提交到服务端。此时http请求的头部信息会包含:Cookie:PHPSESSID=ug9gch0ns7nql4gjoe3jckdab2

 

5、当数据到达服务端,PHP会根据cookie内容找到session文件SESS_ ug9gch0ns7nql4gjoe3jckdab2 并将该文件读入$_SESSION 变量。然后验证用户名和密码。验证通过了。就将该用户的相关信息,比如用户名、系统权限等写入到$_SESSION 变量中。cookie没有改变。脚本执行结束时,$_SESSION变量的值会被序列化后写入SESS_ ug9gch0ns7nql4gjoe3jckdab2 文件。

验证不通过,则跳转回登录页,cookie没有改变,$_SESSION也没有新增值。

 

6、如果用户完成登录进入系统了,以后每访问一个页面,系统会获取该客户端浏览器传过来的cookie值,然后根据cookie值获取到对应的session文件,读取session文件并解序列化写入到内存中即$_SESSION变量中。接着服务端系统接口处会验证该$_SESSON文件中是否有之前设置的用户信息,如用户名和系统权限等。如果有,则说明该用户已经登录,如果没有,则说明该用户登录过期或者未登录,跳转到登录页面。

使用cookie来实现登录就不会再使用到session了。如文章开头所述,cookie实现登录需要将用户的信息进行单向加密。然后通过验证该密文确认用户是否已经登录。也许大家会感觉使用session验证登录的步骤比cookie的简单许多。其实只是需要我们处理的步骤比较少而已,有一部分是语言编译器内部实现的。比如session文件的生成匹配。所以到我们自己操作的步骤就会相对较少。cookie实现登录主要依靠单向加密验证,比如用户登录时对”用户名+用户密码+cookie过期时间+盐”这些信息进行md5签名,然后将该签名放到cookie中,当然cookie值还包含用户名和cookie值的过期时间,比如:admin_1533006028_ bbf2c2b1ec5cfb62d0a30438d8d0305c。后面用户每次访问都获取到这个cookie值,拆分后根据用户名和cookie值的过期时间,加上从数据库获取的用户密码和盐值,进行md5签名,然后对两步签名进行比对,如果一致,则说明是已登录的用户。

由于用户每次访问都要验证cookie里的签名,也就是每次都要获取用户密码和盐值。一般这些信息都是存在数据库中。所以使用cookie实现登录,会对数据库的用户表造成极大的压力。而session方式则不存在这个问题,因为session是存在文件中,用户每次访问,PHP会将该用户对应的session文件读入内存。然后再去访问$_SESSION变量获取。但是session这样处理的缺点是,当用户量特别多的时候,每个用户都会产生一个session文件,这意味着服务器的压力倍增。就算做分布式,也还要处理session的集群。

当然,session也可以写入数据库,或者写入缓存。如果session写入数据库,那么又回到刚才cookie每次访问都要查询数据库的问题了。如果是写入缓存,倒也是权宜之计。如果在使用cookie登录的步骤中将用户信息写入缓存,那么这种方式也可以减缓数据库的压力。每次验证时如果缓存中没有再去查询数据库。这样也不失为一个可行之计。

当然,也可以对用户表进行分表并作一主库多从库处理。在大用户量情况下,单使用数据库,应该也能支撑吧。

免责声明:文章转载自《使用COOKIE实现登录 VS 使用SESSION实现登录》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇R 报错的问题Ubuntu安装VMware Tools下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

nodejs--Nodejs单元测试小结

前言 最近在写一课程的Project,用Node写了一个实时聊天小应用,其中就用到了单元测试。在写Node单元测试的时候,一方面感受到了单元测试的重要性,另一方面感受到了Node单元测试的不够成熟,尚未有成熟的理论体系,所以想写篇博客探讨一下Node里面单元测试的方法。示例代码部署在Github上面,地址是:https://github.com/blogd...

Java Servlet 中文API说明

JavaServlet中文API说明 这份文档描述了Java Servlet API的最新版本2.1版。所以,这本书对于Servlet的开发者及servlet引擎的开发者同样适用。 Java Servlet API的组成 Java Servlet API由两个软件包组成:一个是对应HTTP的软件包,另一个是不对应HTTP的通用的软件包。这两个软件包的同时...

提升权限令牌

提权相关函数: GetCurrentProcess() 介绍: 功能:检索当前进程的伪句柄。 函数原型:HANDLE GetCurrentProcess(); 返回值:返回值是当前进程的伪句柄。 OpenProcessToken() 介绍:功能:打开与进程相关联的访问令牌。 函数原型:BOOL WINAPI OpenProcessToken(      ...

WebSocket-java实现

一、所需jar 二、创建websocket.jsp(注意此页面链接,需要链接到自己的服务) 1 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> 2 <% 3 String path = request.getContextPath...

python如何获取公众号下面粉丝的openid

如何获取公众号下面粉丝的openid呢,首先要获取一个access_token,这个token可不是令牌(Token),如何获取这个access_token呢?有两种方法,方法如下: #-*- coding: cp936 -*- #python 27 #xiaodeng #原文在 https://www.cnblogs.com/dengyg200891/p...

spring-session之二:简单配置

官方示例:https://docs.spring.io/spring-session/docs/current/reference/html5/#samples 配置Spring Session 在Web项目中配置Spring Session分为四步: 搭建用于Spring Session的数据存储 将Spring Session的jar文件添加到...