草庐IT

Cookie和Session详解

小小太空人w 2023-04-14 原文

目录

前言:

Session详解

Cookie和Session区别和关联

服务器组织会话的方式

使用Tomcat实现登录成功跳转到欢迎页面

登录前端页面

登录成功后端服务器

重定向到欢迎页面

抓包分析交互过程

 小结:


前言:

    Cookie之前博客有介绍过,就是服务器在用户这边搞的一个持久化存储机制。通过服务器这边set-cookie进行设置,用户发起请求通过cookie字段将cookie中的内容发送到服务器,服务器就知道客户端这边处于一个什么样的状态。

    Session是搭配Cookie使用的(也可以不搭配)。对于一个登录需求来说,通过用户的SessionId(存储在Cookie中),服务器这边就可以判断用户是否处于一个登录状态。

Session详解

注意:

    服务器不知道我的身份信息。针对登陆操作,淘宝会查询数据库,验证用户名和密码是否正确,如果正确则登录成功,淘宝会把当前的身份信息在内存中存一份。

    同时给这个用户分配一个表示身份信息的序号,整数或者字符串,具有唯一性(sessionId)。服务器使用像hsah表这样的结构,把序号作为key,身份信息作为val,存储起来(这些键值对称为session)。

    服务器通过Set-Cookie将SessionId保存到用户本地。后续请求中,服务器收到Cookie中的身份序号(SessionId),就会查询上述的hash表,判断用户是谁(避免重复输入账号密码),如果没查到,则需要用户重新登录。

Cookie和Session区别和关联

关联:在网站登录功能中搭配使用。

区别:

    1)Cookie是客户端的存储机制,Session是服务器的存储机制。

    2)Cookie里面可以存各种键值对(还可以存别的),Session则专门用来保存用户信息。

    3)Cookie完全可以单独使用,不搭配Session(实现非登录的场景)。Session也可以不搭配Cookie(手机app登录服务器,没有cookie概念,但存在Session,Cookie和浏览器强相关)。

    4)Cookie是Http协议中的一个部分。Session则可以和http无关。

服务器组织会话的方式

注意:

    每一个会话是一个键值对,对应到一个客户端。服务器这里可以对应多个客户端,也就可以保存多组会话。

    每个会话对象HttpSession里,也是以键值对方式保存的。存一些用户信息,这里面内容都是自定义的。Java中通过,setAttribute(),getAttribute()存取键值对。用来设置HttpSession对象里的一些内容。

使用Tomcat实现登录成功跳转到欢迎页面

登录前端页面

    使用from表单构造post请求,将数据通过body传输到后端。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <br>
        <input type="password" name="password">
        <br>
        <input type="submit" value="提交">
    </form>
    
</body>
</html>

登录成功后端服务器

    前端发起post请求,后端Tomcat调用doPost()方法。判断登录,登录成功则创建会话Session。将用户名设置到HttpSession对象中,然后重定向到欢迎页面。

    创建会话Session,每个客户端都会有一个这样的会话,服务器就使用像hash表这样的结构组织这些会话(key:SessionId   val:HttpSession)。

    getSession(true)判断当前请求是否已经有对应的会话(拿着cookie中的sessionId查一下hash表)。如果没有则创建新会话,插入hah表,如果有则返回对应的HttpSession对象。

    getSession(false)获取SessionId对应的HttpSession对象。同样查询hash表,如果查到了则返回对应的HttpSession对象,如果没有则返回null。

    创建过程:1)构造HttpSession对象。 2)构造一个唯一SessionId。 3)把这个键值对插入hsah表。 4)把sessionId设置到响应报文Set-Cookie字段中。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userName = req.getParameter("username");
        String password = req.getParameter("password");

        //判断登录
        if(!userName.equals("zhansan") && !userName.equals("lisi")) {
            System.out.println("登录失败,用户名错误");
            resp.sendRedirect("login.html");
            return;
        }
        if(!password.equals("123")) {
            System.out.println("密码错误");
            resp.sendRedirect("login.html");
            return;
        }
        //登录成功
        //创建会话
        //所谓会话是一个键值对,key是sessionId,value是HttpSession对象
        //每个客户端登录都会有一个这样的会话(键值对),服务器需要管理多个会话,搞个hash表存储
        //getSession(true)判断当前请求是否已经有对应的会话了(拿着cookie中的sessionId查一下hash表)
        //如果SessionId不存在,就创建新会话,插入hash表,如果查到了就返回对应会话
        //创建过程:1)构造HttpSession对象 2)构造一个唯一sessionId 3)把这个键值对插入hsah表 4)把sessionId设置到响应报文Set-Cookie字段中
        HttpSession session = req.getSession(true);

        //HttpSession对象也是一个键值对
        //setAttribute(),getAttribute()存取键值对
        //把当前用户名保存到会话中
        session.setAttribute("username", userName);
        //重定向到主页
        resp.sendRedirect("index");
    }
}

重定向到欢迎页面

    先判断用户是否登录,如果没有登录则重定向到登录页面。登录成功后构造欢迎页面,将用户名显示到页面中。只要登录成功后续请求多次服务器,Cookie字段都会包含SessionId。

    由于这个页面是重定向的,浏览器会发起get请求,这里就需要重写doGet方法。

    这里需要先获得用户的HttpSession对象,通过getSession(false)获取SessionId对应的HttpSession对象。如果返回值为null则用户没登录,否则登录成功构造欢迎页面。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    //通过重定向,浏览器发送get请求

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先判断用户是否登录,如果没登陆重定向到登录页面
        //已经登录,根据会话中的用户名,显示到页面中
        //这个操作不会触发会话的创建,根据sessionId查找HttpSession对象(根据key查找value)
        HttpSession session = req.getSession(false);
        if(session == null) {
            System.out.println("用户未登录");
            resp.sendRedirect("login.html");
            return;
        }
        //登录成功
        String userName = (String) session.getAttribute("username");
        //构造页面
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("欢迎" + userName + "回来");
        //只要登录成功,后续请求都会带上刚才这个cookie(包含sessionId)
    }
}

抓包分析交互过程

 小结:

    这里的代码需要理清每次请求和响应的具体逻辑。根据这些需求约定好前后端交互接口,代码实现需要严格按照约定来实现。

有关Cookie和Session详解的更多相关文章

  1. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

  2. ruby-on-rails - Rails Cookie 问题 - 2

    我在ruby​​onrails应用程序中有以下新方法:defnewifcookies[:owner].empty?cookies[:owner]=SecureRandom.hexend@movie=Movie.new@movie.owner=cookies[:owner]end基本上,每个新用户都应该获得一个代码来识别他们(尽管只是通过cookie)。因此,当用户创建电影时,创建的cookie将存储在owner字段中。所以有两个问题:使用.empty?方法,当我从浏览器中删除cookie时,返回一个undefinedmethodempty?'对于nil:NilClass`当我确实已经在

  3. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  4. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

  5. ruby - Sinatra session 未按预期持续 - 2

    我正在尝试使用Sinatra中的重定向和session在网站周围传递一些数据。这是一个简化的示例,使用PrettyPrint进行调试:require'pp'require'rubygems'require'sinatra'enable:sessionsget'/'dosession[:foo]='12345'puts'session1'ppsessionredirectto('/redir')endget'/redir'doputs'session2'ppsession'helloworld'end查看Thin的输出,我看到:>>Listeningon0.0.0.0:4567,CTRL

  6. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  7. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  8. ruby-on-rails - 自定义设计 Cookie - 2

    我在我的Rails应用程序中使用设计。我在租户庄园中配置了它,其中帐户/session的范围限定为子域。例如:http://subdomain1.example.com/http://subdomain2.example.com/...这很好用,但我想为“super管理员”添加一个子域,允许这些用户导航到所有其他子域而无需重新验证。这将是这样的:http://admin.example.com/是否可以自定义仅在管理子域上生成的cookie,以便它在所有其他子域上都有效? 最佳答案 Cookie域的定义越不具体,它们的包容性就越大,

  9. ruby - 如何强制 Rack :session + sinatra to read "rack.session" from params instead of cookies - 2

    我正在处理oauth1.0(twitter和flickr)。网站工作在80端口,oauth服务器工作在8080端口算法:向oauth服务器发送ajax请求以检查用户是否有有效的access_token如果用户没有access_token或access_token已过期,则打开授权窗口在oauth服务器的用户session中保存access_token发送分享数据到oauth服务器它使用sinatra+rack:session+rack::session::sequel+sqlite来存储session。它在每个响应中发送Set-Cookie:rack.session=id我正在使用2种

  10. ruby-on-rails - 如何编写 Rails 4 测试以使用 omniauth-google-oauth2 gem 创建 session ? - 2

    我正在尝试为使用omniauth-google-oauth2gem创建session编写测试。我是否需要将env["omniauth.auth"]变量与post:create一起传递?也许当我试图这样做时,我做错了。我得到的错误如下所示...Rake测试错误1)Error:SessionsControllerTest#test_should_get_create:NoMethodError:undefinedmethod`provider'fornil:NilClassapp/models/user.rb:6:in`from_omniauth'app/controllers/sessi

随机推荐