cookie和session的区别(总结)

一、cookie产生的缘由
1.新的需求产生的产生
随着web网站的快速发展,网站已经不再用于单纯的信息展示,而是一个庞大的具有交互式的多网页的应用。在web应用中,信息的登录是一种很常见的功能,登录后页面跳转必须保持登录状态,不能但是每一次页面跳转都需要重新登录。在这样的需求下cookie应运而生。

2.为什么要使用cookie
在前端与后台的http联系中,单纯从请求来说是一个独立的过程。(也就是说发送一个请求,抛开数据内容,后台不知道也不关注上一次是否发送过信息)。但是有些时候我们想让后台知道上一次或前几次的请求信息,这时就需要在发送的内容上做文章。向后台发送一些想让后台知道的,上次请求的情况。而部分内容就是cookie。
二、cookie

  1. 什么是cookie
    cookie就是一个数据,cookie就是一种让后台知道,之前请求情况的数据。那么我们就要关心,数据的内容和存储方式。我们知道一般都是前端发送包含cookie请求到后台,后台通过cookie来了解之前访问的情况,那么cookie一定是存储在前端的。。至于存储的内容,由前后端协商设计。后台需要了解什么信息就存储什么信息。同时cookie也可以存储一些不太重要的信息(如曾经浏览的商品,购物车内容)
    2.cookie的特点
    a.存储在浏览器中
    浏览器记录上次请求的数据,下一次请求发给后台,并记录这次返回的信息。
    也可以记录一些不重要的信息,为后台减轻存储压力

    b.存储容量较小(一般4KB)
    cookie由于每次请求都要向后台发送数据,所以容量要有限制,否则会大大降低网络传输效率。

    c.不安全(可以修改或是伪造)
    由于数据在浏览器中存储,任何人都可以随意进行更改,达到欺骗后台的目的。所以cookie存储一些不太重要的信息,对于一些重要信息要进行防篡改和加密处理。

3.cookie使用流程
首次浏览器访问后台,有后台分配cookie给浏览器,浏览器保存cookie
浏览器第二次访问,将保存的cookie发给后台,后台识别确认并更新cookie,返回浏览器再次保存
4.cookie的属性
name:一个唯一确定的cookie名称。通常来讲cookie的名称是不区分大小写的。一般可用UUID生成。

value:存储在cookie中的字符串值。最好为cookie的name和value进行url编码

domain:cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:
yq.aliyun.com),也可以不包含它(如:.aliyun.com,则对于aliyun.com的所有子域都有效,这里子域表示网站的二级域).

path: 表示这个cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送cookie。

expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。

max-age: 与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒),而不是一个固定的时间点。正常情况下,max-age的优先级高于expires。

HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。

secure: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放cookie就对了服务器端设置。

5.cookie的应用
cookie最大的一个用途就是,浏览器跳转保持登录和短时间免登陆。
cookie还有一个用途就是,保存一些不重要的信息,如:曾经浏览的商品等。
cookie目的是为曾经使用过该网站的人提供一些数据保存。

三、session
为解决cookie不安全的问题,我们使用session,来提高网站安全性。
我们知道由于cookie是保存在客户端上的,所以有被篡改的风险,不安全。要保存重要的数据一定要保证不会被篡改才是安全的,如果文件存储在服务器端,用户无法私自进行修改,那么安全性就会大大提高。session就是一种服务端存储信息的方式。

1.什么是session
session是保存在服务器上的数据,是基于cookie的,是为了给浏览器在服务器端储存自己独有数据的一个集合。通过setAttribute()方法存数据,getAttribute()方法取数据。

2.session原理
session是一种基于cookie的存储方式。说的通俗一点,session负责存储数据,cookie负责告诉后台,是哪一个数据。当建立一个新session的时候,向客户端下发一个session-id,让客户端保存session-id在cookie中,下一次发起请求的时候,将session-id发回后台,后台通过session-id,在很多session中查找到相应session-id对应的session进行操作。
注意:
session有过期时间:我们可以设置session的过期时间,当时间到达设置后,销毁session,以节约空间。默认不设置的话保持30分钟。
有两种设置Session的方法:
(1)setMaxInactiveInterval()方法,单位秒
(2)在web.xml中配置 ,单位分钟

  <session-config>
    <session-timeout>20</session-timeout>
  </session-config>

3.session与数据库的对比
我们知道session和后台数据库都是在服务端的数据存储方式。那么这两者有什么区别呢?

访问速度:session的数据存储在内存中,session的操作比数据库要快很多,单纯的读取速度大概是后者的10000倍。在高并发的时候,使用session处理不需要长期保存的文件,效率是极高的。
数据库的信息是一定要长期保存的。session的访问依赖于前端的session-id,如果用户删除掉cookie中的session-id,那么对session信息就难以操作。
我们可以把session理解为,一种不需要长期保存的带时间销毁机制的高速数据库。

4.session的使用应注意
session-id为服务器自动生成的,它的maxAge属性一般为-1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。

如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。

session的默认失效时间是20分钟

session不能替代数据库,不能将session时间设置为无限长,这样会导致内存占用过大。当然session的数据也可以写入数据库中,长期保存。

四、安全性
1、cookie防篡改
cookie作为登录状态保存在前端,有被篡改的可能。通过添加签名的方式,提升安全性。签名的作用不是禁止恶意修改,而是可以看出是否有修改过。如果被修改过,那么服务端判定cookie无效。

2、加密
cookie也可以加密保存在前端,但是实际意义不大,重要的信息一般保存在session。cookie如果存有重要信息,就算再严谨的加密方式,总会有破解的可能。安全性不如session。

3.复制尝试破解
cookie就是一个状态验证,如果有人复制走你的cookie信息,尝试利用cookie登录你的账户。后台是无法分辨登录的合法性。此类安全问题无法避免(cookie就相当于你的账户,密码。如果有人恶意获取cookie,就相当于获取了账户和密码),技术有提供方便,就会带来风险。
解决方案:提示用户选择是否保存cookie,验证cookie发送ip是否异常
以上内容参考博文:https://blog.csdn.net/konghouy/article/details/83015236

五.Cookie和Session实现用户登录保存用户登录状态一定时间免登陆。

1.需求分析:
  首先,用户登录成功后保存用户登陆的用户名到Cookie,同时设置Cookie的有效时间,在下次用户想免输入登陆时,直接判断Cookie是否含有该用户的用户名,如果有则直接登陆不需要输入,否则需要重新输入用户名和密码。
  
2.代码实现:
(1)KeepLoginServlet(用户登录)

@WebServlet("/keeploginservlet")
public class KeepLoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public KeepLoginServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            //获取HTTPSession对象
        HttpSession session = request.getSession();   
        request.setCharacterEncoding("utf-8");//设置编码格式
        response.setContentType("text/html;charset=utf-8");//设置返回的响应页面

        // 从session中获取验证码
        String vcode = (String) session.getAttribute("vcode");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String code = request.getParameter("code");

        PrintWriter out = response.getWriter();

        if (!vcode.equals(code)) {
            out.write("<html>"
                    + "<head><script type='text/javascript'> alert('验证码错误!');location='login.html';</script></head>"
                    + "<body></body></html>");
            return; // 不继续执行,重新返回login.html页面
        }

        if ("123".equals(username)) {
            if ("123".equals(password)) {

                // 创建cookie并将成功登陆的用户保存在里面
                Cookie cookie = new Cookie("username", username);
                cookie.setMaxAge(60); // 设置一分钟有效
                response.addCookie(cookie); // 服务器返回给浏览器cookie以便下次判断

                response.sendRedirect(request.getContextPath() + "/index.html"); // 重定向到index.html
            } else {
                out.write("<html>"
                        + "<head><script type='text/javascript'> alert('密码错误!');location='login.html';</script></head>"
                        + "<body></body></html>");
                return;
            }
        } else {
            out.write("<html>"
                    + "<head><script type='text/javascript'> alert('不存在该用户!');location='login.html';</script></head>"
                    + "<body></body></html>");
            return;
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在这判断用户输入是否正确是一个工具类,如果用户登录成功则将这个用户保存到Cookie里,设置过期时间为1分钟,以便下次免登陆。

(2)KeepLoginServlet(验证码)
  这里为了节省空间直接给出doGet方法,这里有一个验证码的jar包ValidateCode .jar非常方便大家可以自行查找。地址是(@WebServlet(“/vcodeservlet”))

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();

        //创建验证码图片流
        ValidateCode validateCode = new ValidateCode(120,50,4,20);
        validateCode.write(response.getOutputStream());

        //将验证码存入session中
        session.setAttribute("vcode", validateCode.getCode());
    }

(3)FindCookieServlet(判断用户是否可以免登陆)
  这里是实现的逻辑是:遍历所有cookie看是否含有username,如果含有username说明用户登陆过,可以免输入直接登陆。地址是(@WebServlet(“/dindcookieservlet”))

protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        boolean flag = false;
        PrintWriter out = response.getWriter();

        // 判断cookie是否有username,如果有代表登陆过
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                System.out.println(URLDecoder.decode(cookie.getName(), "utf-8"));
                if (URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { // 表明已经登陆过了,就直接跳转了
                    flag = true;
                }
            }
        }

        if(flag) {
            response.sendRedirect(request.getContextPath() + "/index.html");

        }else {
            out.write("<html>"
                    + "<head><script type='text/javascript'> alert('没有登陆过,请登录!');location='login.html';</script></head>"
                    + "<body></body></html>");
        }

(4)ReturnClearCookie(清除用户保存的cookie)
  Cookie是没有直接删除指定cookie的方法的,所以我可以找到cookie里的username并把他的有效时间设置成0秒,这样间接实现了删除Cookie里的username。地址是 (@WebServlet(“/returnclearcookie”))。

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //这里就是把username的cookie设置成0秒有效期,就是直接删除掉了
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                System.out.println(URLDecoder.decode(cookie.getName(), "utf-8"));
                if (URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { // 表明已经登陆过了,就直接跳转了
                    cookie.setMaxAge(0);
                    response.addCookie(cookie);
                }
            }
        }
response.sendRedirect(request.getContextPath()+"/login.html");
    }

(5)两个页面
  login.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面</title>
<style type="text/css">
.dv_error {
    color: red;
}
</style>
</head>
<body>
    <form action="/myday13_zhuangtaiguanli/keeploginservlet" method="post">
        <label>账号:</label><input type="text" id="username" name="username"><br />
        <label>密码:</label><input type="password" id="password" name="password"><br />
        <label>密码:</label><input type="text" id="code" name="code"><img id="img1" src="/myday13_zhuangtaiguanli/vcodeservlet" "changeImg()" /><a href="javascript:void(0)" "changeImg()">看不清换一张</a><br />
        <input type="button" "check()" value="登录">
        <label><a href="/myday13_zhuangtaiguanli/dindcookieservlet" >已经登陆,直接登陆</a></label>
    </form>
    <script type="text/javascript">
         function check(){
             var username = document.getElementById("username")
             var password = document.getElementById("password")
             var code = document.getElementById("code")
             if(username.value == ""){
                 alert("请输入用户名")
             }else if(password.value == ""){
                 alert("请输入密码")
             }else if(code.value == ""){
                 alert("请输入验证码");
             }else{
                 document.forms[0].submit()
             }
         }
         function changeImg(){
             var img1 = document.getElementById("img1")
             img1.src="/myday13_zhuangtaiguanli/vcodeservlet?num"+Math.random();
         }
    </script>
</body>
</html>

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>欢迎登录...</h1>
<a href="/myday13_zhuangtaiguanli/returnclearcookie">退出登陆并不保留登陆信息</a><br/>
<a href="login.html">退出登录,但5分钟内免登陆</a>
</body>
</html>

以上参考原文:https://blog.csdn.net/a754895/article/details/82632747

其他相关代码实现可参考:
Cookies 和 Session的区别:https://blog.csdn.net/axin66ok/article/details/6175522
Cookie/Session机制详解:https://www.cnblogs.com/liuwei0824/p/7699632.html
JavaWeb使用Session和Cookie实现登录认证:https://www.jb51.net/article/108764.htm

猜你喜欢

转载自blog.csdn.net/workingman_li/article/details/89397159