草庐IT

Cookie 和 Session

鸢也 2024-06-11 原文

Cookie 和 Session

文章目录


前言:

这篇帖子重点讲讲Cookie和Session之间的区别,以及作用,Cookie在http协议中就提到了他的定义,作用,小伙伴们可以跳转到 Http协议 这个页面看看Cookie的基本概念及作用。

前情回顾:

1、Cookie是浏览器提供的一种让程序员在本地存储数据的能力,让数据在客户端这边更持久化。

2、Cookie里面存的是键值对的格式数据,键值对用“;”分割,键和值之间用“,”分割。

3、浏览器里面存的Cookie都是从服务器的响应“报头”里面的 set-cookie 字段中来的,每个 set-cookie 字段里面都包含一个Cookie 这样的键值对,浏览器拿到响应之后就会把 set-cookie中的内容保存到本地,而 set-cookie 就是程序员自己在服务器中构造填写的。

经典cookie运用场景,保存用户登录信息:

在传输的过程中,cookie不仅保存了我们的用户名和密码还保存了我们账户的其他信息,像这样明文传过来传过去,显然是不安全的,再加上cookie存储的信息数据也是非常庞大,每次传输都需要传很多数据,也是非常占用带宽,之前也说了带宽占的资源多,成本也多,像这么数据庞大的传输,钱也在烧,然后传输的数据也不安全,所以就有了一个解决的办法,就是用session!!!

一、session

session中文翻译是“会话”,session是在服务器的一种机制,因为cookie是客户端保存的数据,而这些数据又是跟用户强烈相关联的,显然保存在客户端这边就不太合适(太多,也占资源),所以把数据都保存在服务器这边就比较的合适;保存的方式就是通过session的方式来进行保存的。

1.怎么保存?

a、服务器这边根据用户登录成功,就会生成一个键值对:

​ key:SessionId,是一个随机,不重复的,唯一的字符串

​ value:是用来保存客户身份信息

​ 服务器以“键值对”的方式来把这些session(会话)给管理起来,每个用户的登录都会生成一个会话。

里面的键值对就可以直观想象成一个哈希表!!!

b、客户端只需要保存 sessionId就可以了,后续的请求带上 sessionId,服务器就会根据 sessionId 就会找到对应的用户数据详细的信息。

用session的好处:

1、客服端很轻量,不用存储大多的数据

2、客户端和服务器之间传输的数据量小,节省带宽

3、数据都在服务器中保存,如果客户端出现问题,数据是不会丢失的。

二、Cookie和session的区别

面试官常考题,赶快拿小本本记下来😁😁😁

1、Cookie是客户端(浏览器)存储数据的一种机制,键值对结构,可以存储身份信息,也是可以存储关键的信息,都是程序员自定义,

题外话,浏览器中网页JS代码是禁止访问电脑磁盘,而不是浏览器本身不能访问

2、Session是服务器存储数据的一种机制,键值对结构的,主要用来存储身份相关的信息。

3、Cookie和Session经常在一起配合使用,但也不是必须配合

三、servlet中对Cookie和Session提供的封装

HttpServletRequest 类中的相关方法 :

方法描述
HttpSession getSession()在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果 为 false, 则当不存在会话时返回 null
Cookie[] getCookies()返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把 Cookie 中的格式解析成键值对.

getCookies()方法,是在HttpServletRequest对象中,能够获取到当前请求中的所有Cookie,一个请求中有多个Cookie键值对,每个Cookie键值对,就对应到一个Cookie对象,Cookie对象里面有两个核心的方法:getKey,getValue

但是实际上使用getCookies()方法很少用,更多的时候使用的是getSession()这个方法。

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 doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
        // 设置utf8,防止页面乱码
        resp.setContentType("text/html;charset=utf-8");
        // 获取用户名和密码,以username=admin&password=123 这种形式获取就用 getparameter() 来操作。
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if (username == null || "".equals(username) || password == null || "".equals(password)) {
            resp.getWriter().write("<h3>用户名和密码位空</h3>");
            return;
        }

        if (!username.equals("admin") || !password.equals("123")) {
            resp.getWriter().write("<h3>用户名或密码错误</h3>");
            return;
        }
		
        // 在服务器中获取会话,参数true,则没有SessionId就会创建SessionId键值对插入到服务器当中。
        HttpSession session = req.getSession(true);  //!!!!!!!!!!!!!
        // HttpSession对象中,根据Key来设置value
        session.setAttribute("visitCount", 0);

        // 登录结果反馈给客户端,反馈的是跳转页面,而不是登录成功
        //  我们需要重定向这个操作
        resp.sendRedirect("index");
    }
}

这段代码是实现用户登录成功的案列,成功的结果就是重定向跳转其他的页面

HttpSession session = req.getSession(true); //getSession()里面的参数是Boolean类型

1、如果参数是true,就会看看请求中是否会有 SessionId,以及SessionId合不合法,如果有SessionId,就会根据这个SessiuonId找到对应 HttpServlet 对象(查hash表),在服务器这边以一个hash表的形式,把若干个Session给组织起来;

​ 如果没有SessionId,那么服务器就会生成一个SessionId,同时创建一个HttpServlet 对象,把这一组键值对再插入到服务器管理的Session的hash表中,同时把 sessionId,通过Set-cookie 在响应中返回给客服端

2、如果参数是false,也是会看请求中是否有SessionId,以及是否合法,如果有SessionId,直接找到对应的 HttpServlet对象,查询各方面的信息,

​ 如果没有SessionId,那么直接返回就是null

关于HttpServlet,再次强调,HttpSerblet对象里面存储的是身份数据信息,每个用户登录都会有自己的身份数据信息,此时服务器上就会有很多的HttpSerblet对象了,而这个HttpServlet对象,是有键值对hash表的方式组织管理而成的

**HttpSession ** 类中的相关的方法:

一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息

方法描述
Object getAttribute(String name)该方法返回在该 session 会话中具有指定名称的对象,如果没 有指定名称的对象,则返回 null.
void setAttribute(String name, Object value)该方法使用指定的名称绑定一个对象到该 session 会话

在HttpServlet对象中,也是存储了键值对的,根据 Key 获取 value值,就叫 getAttribute,根据 Key 设置 value,就叫setAttribute。

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 {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置utf8,防止页面乱码
        resp.setContentType("text/html;charset=utf-8");
        // 获取会话,false说明没有Session,则返回null
        HttpSession session=req.getSession(false);
        if (session == null) {
            resp.getWriter().write("<h3>当前你尚未登录</h3>");
            return;
        }
        // 因为getAttribute()是object类,所以要强制转换成Integer
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        // 拿到上次的访问次数的值,现在有访问了一次所以 + 1
        visitCount +=1;
        // 把这个值写回到 session 中, 以备下次访问中使用.
        session.setAttribute("visitCount",visitCount);
        resp.getWriter().write("<h3>visitCount:"+ visitCount+"</h3>");

    }
}

这段代码是实现一个登录的案列,记录的是当前客服访问的次数。在上一段代码中session.setAttribute("visitCount", 0);就已经在HttpServlet中设置了访问次数,然后这段代码就是获取到上次代码的访问次数0,然后然后访问成功就visitCount+=1,最后就是把值写到session中,以备下次使用,然后在从页面中打印出来。


总结:(八股文)

实现一个登录的常规流程:

1、读取用户的用户名和密码(这个需要前端代码)

2、对用户名和密码进行校验

3、判断是否登录成功

4、创建会话,保存自定义信息

5、重定向到登录成功的主页面。


以上信息存储在session(会话)中都是,存储在内存中的,也就是说服务器重新启动过后,session信息就会没有,需要重新登录获取信息才行。

第一次登录抓包:

登录成功后:

登录成功后,服务器就会存储这个Session(会话),下一次客服端拿着SessionId就可在服务器会话中找到对应的键值对。

如果重启服务器,session里面的数据就会全部消失!!!

再次请求,原来的SessionId都还在,但是拿着这个SessionId去服务器找的话,就会找不到。

只有客服端再次登录成功生成新的SessionId,再给客服端分配新的SessionId,客户端又可以反复使用了。

这篇帖子的代码,在gitee上:servlet02


这是在我们进行网络传输登录中Cookie和Session的工作流程,两个都是互相配合,共同实现的。觉得博主写的不错就,收藏关注呗❤🧡💛💚💙💜🤎🖤🤍💟,你们支持就是我写博客最大的动力!!!!

有关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. ruby-on-rails - 自定义设计 Cookie - 2

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

  7. 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种

  8. 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

  9. ruby - session 未创建 : Chrome version must be between - 2

    当使用ruby​​selenium驱动程序驱动chrome时,我得到/home/travis/.rvm/gems/ruby-2.6.2/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/remote/response.rb:72:in`assert_ok':sessionnot创建:Chrome版本必须在70和73之间(Selenium::WebDriver::Error::SessionNotCreatedError)如何解决这个问题?降级chrome不是我想做的事。 最佳答案

  10. ruby - 是否有 Rack::Session::Cookie 用法的基本示例? - 2

    我找不到任何使用Rack::Session::Cookie的简单示例,并且希望能够将信息存储在cookie中,并在以后的请求中访问它并让它过期.这些是我能找到的唯一示例:HowdoIset/getsessionvarsinaRackapp?http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html这是我得到的:useRack::Session::Cookie,:key=>'rack.session',:domain=>'foo.com',:path=>'/',:expire_after=>2592000,:secret=

随机推荐