ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java之Cookie和Session

2021-09-22 23:03:13  阅读:85  来源: 互联网

标签:java String Session bean session Cookie import cookie


一、会话

1、会话:一次会话中包含多次请求和响应。

  • 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止

2、功能:

  • 在一次会话的范围内的多次请求间,共享数据

3、方式:

客户端会话技术:Cookie
服务器端会话技术:Session

4、http协议无状态

状态的含义:

客户端域服务器在某次会话中产生的数据,这些数据存在于缓存区中,缓存区中存储、记忆、共享一些临时数据,从而无状态就意味着,这些数据不会被保留。

无状态的官方解释:

  1. 协议对于事务处理没有记忆能力
  2. 对同一个url请求没有上下文关系
  3. 每次的请求都是独立的,它的执行情况和结果与之前的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
  4. 服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器。

但是,通过增加cookie和session机制,现在的网络请求其实是有状态的。
在没有状态的http协议下,服务器也一定会保留你每次网络请求对数据的修改,但这跟保留每次访问的数据是不一样的,保留的只是会话产生的结果,而没有保留会话。

举例思考:

假如没有cookie没有session,http无状态的时候,当一个用户访问网站的时候,会有下面的问题:
你每访问一次需要权限的内容都需要在客户端输入用户名和密码。
你的每一次操作都要与系统底层的数据库进行交互(多次少量的访问存在非常大的性能浪费。非常容易就能想到肯定是一次大量的操作更有效率,于是就想到了缓存区)
你的非重要琐碎数据也被写进数据库中,跟你的主要数据放在一起(一次次添加和删除购物车只是跟你这次浏览,或者叫这次会话有关,是临时的数据,跟用户的主要信息无关,它们没什么价值,纯粹的冗余数据,用什么存放这些临时的数据,我们也很容易想到缓存区。)
上面就是无状态时候,会出现的问题,即使有连接,也无法解决【每一次操作都要与系统底层的数据交互】的问题,要解决【每一次操作都要与系统底层的数据库进行交互】就必须在服务端开辟一块缓存区。

二、cookie

1、概念:

客户端会话技术,服务端给客户端的数据,存储于客户端(浏览器)。由于是保存在客户端上的,所以存在安全问题,并且cookie是由个数和大小限制的(4KB),所以一般cookie用来存储一些比较小且安全性要求不高的数据,而且一般数据都会进行加密。

我们平时在登录某些网站时,关闭浏览器后再次打开登录,用户名密码等数据会自动填充在表单。
或者我们浏览淘宝的某个商品后,下次再打开发现出现的商品很多都是我们之前浏览的同类商品等。
这些都是cookie的应用场景。

2、快速入门

使用步骤:
创建Cookie对象,绑定数据
new Cookie(String name, String value)
发送Cookie对象
response.addCookie(Cookie cookie)
获取Cookie,拿到数据
Cookie[] request.getCookies()

3、实现原理

基于响应头set-cookie和请求头cookie实现

4、cookie的细节

1.一次可不可以发送多个cookie?

  • 可以
  • 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。

2.cookie在浏览器中保存多长时间?

默认情况下在浏览器关闭后就会失效。即一次会话后就失效。因为cookie是放在浏览器缓存的,浏览器关闭会清除缓存所以cookie会失效。

要想使这个cookie在浏览器关闭后仍然有效就需要设置有效时间将其写到磁盘下。

持久化存储:

  setMaxAge(int seconds)
    正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
    负数:默认值
    零:删除cookie信息
3.cookie能不能存中文?

  1. 在tomcat 8 之前 cookie中不能直接存储中文数据。

    需要将中文数据转码---一般采用URL编码(%E3)

  1. 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析

4.cookie共享问题?

4、1假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

  1. 默认情况下cookie不能共享
  2. setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
  3. 如果要共享,则可以将path设置为"/"

4、2不同的tomcat服务器间cookie共享问题?

  1. setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
  2. setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

5、Cookie的特点和作用

cookie存储数据在客户端浏览器
浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)

作用:

cookie一般用于存出少量的不太敏感的数据
在不登录的情况下,完成服务器对客户端的身份识别

6、Cookie的生命周期

Cookie也是一个类,我们需要关注一下它什么时候生成什么时候消亡。这样我们才能更好的确定何时获取Cookie
Cookie的出生

当执行完这句代码的时候就代表这个Cookie诞生
Cookie cookie = new Cookie(String name,String value);

Cookie的消亡

默认情况下,在你关闭客户端后Cookie就会消失。此时你去获取cookie会返回null
如果设置了有效时间后则需要在有效时间到期后才会消亡。

7、代码示例

package com.stuwork.crowdfunding.controller;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.stuwork.crowdfunding.bean.Member;
import com.stuwork.crowdfunding.bean.Permission;
import com.stuwork.crowdfunding.bean.User;
import com.stuwork.crowdfunding.manager.service.UserService;
import com.stuwork.crowdfunding.potal.service.MemberService;
import com.stuwork.crowdfunding.util.AjaxResult;
import com.stuwork.crowdfunding.util.ConstUtil;
import com.stuwork.crowdfunding.util.MD5Util;

@Controller
public class DispatcherController {

    @Autowired
    private UserService userService;
    
    @Autowired
    private MemberService memberService;
    //跳转到web-inf的index页面。
    @RequestMapping("/index")
    public String index (){
        return "index";
    }
    //跳转到登录页面
    @RequestMapping("/login")
    public String login(HttpServletRequest request,HttpSession session){
        //判断是否需要自动登录
        //如果之前登录过,cookie中存放了用户信息,需要获取cookie中的信息,并进行数据库的验证
        
        boolean needLogin = true;
        String logintype = null ;
        Cookie[] cookies = request.getCookies();
        if(cookies != null){ //如果客户端禁用了Cookie,那么无法获取Cookie信息
            
            for (Cookie cookie : cookies) {
                if("logincode".equals(cookie.getName())){
                    String logincode = cookie.getValue();
                    System.out.println("获取到Cookie中的键值对"+cookie.getName()+"===== " + logincode);
                    //loginacct=admin&userpwd=21232f297a57a5a743894a0e4a801fc3&logintype=1
                    String[] split = logincode.split("&");
                    if(split.length == 3){
                        String loginacct = split[0].split("=")[1];
                        String userpwd = split[1].split("=")[1];
                        logintype = split[2].split("=")[1];
                        Map<String, String> mapParam = new HashMap<String, String>();
                        mapParam.put("loginacct", loginacct);
                        mapParam.put("userpswd", userpwd);
                        mapParam.put("type", logintype);
                        if("user".equals(logintype)){
                            
                            User dbLogin = userService.getUserInfo(mapParam);
                            
                            if(dbLogin!=null){
                                session.setAttribute(ConstUtil.LOGIN_USER, dbLogin);
                                needLogin = false ;
                            }
                            //----------------------------------
                            List<Permission> permissionList = userService.getUserRolePermissionByUserId(dbLogin.getId());
                            Permission permissionRoot = null;
                            Set<String> uris = new HashSet<String>();
                            Map<Integer,Permission> map = new HashMap<Integer,Permission>();
                            for(Permission bean :permissionList){
                                map.put(bean.getId(), bean);
                                uris.add("/"+bean.getUrl());
                            }
                            for(Permission bean :permissionList){
                                Permission children = bean;
                                if(bean.getPid() == 0){
                                    permissionRoot = bean;
                                }else{
                                    Permission parent = map.get(children.getPid());
                                    parent.getChildren().add(children);     
                                }
                            }
                            session.setAttribute(ConstUtil.PERMISSION_ROOT, permissionRoot);
                            session.setAttribute(ConstUtil.URIS, uris);
                            //----------------------------------
                        }else if("member".equals(logintype)){
                            Member dbLogin = memberService.getMemberInfo(mapParam);
                            
                            if(dbLogin!=null){
                                session.setAttribute(ConstUtil.LOGIN_MEMBER, dbLogin);
                                needLogin = false ;
                            }
                        }
                        
                    }
                }
            }
        }
        
        if(needLogin){
            return "login";
        }else{
            if("user".equals(logintype)){
                return "redirect:/main.htm";
            }else if("member".equals(logintype)){
                return "redirect:/member.htm";
            }
       }
       return "login";
    }
    //@RequestParam里的value必须是前端页面name熟悉的值,login可以接收到值(和name属性值一样也可以),否则接收不到
    //同步请求
    /*@RequestMapping("/doLogin")
    public String doLogin(@RequestParam(value="loginacct") String login,
           String userpswd,String type,HttpSession session){
        Map<String, String> map = new HashMap<String, String>();
        map.put("loginacct", login);
        map.put("userpswd", userpswd);
        map.put("type", type);
        
        User user = userService.getUserInfo(map);
        session.setAttribute(ConstUtil.LOGIN_USER, user);
        
        //重定向到主页面,不直接返回main,是防止刷新页面重复提交表单
        return "redirect:/main.htm";
        
    }*/
    //异步请求
    @ResponseBody
    @RequestMapping("/doLogin")
    public Object doLogin(@RequestParam(value="loginacct") String login,
                          String userpswd,
                          String type,
                          boolean rememberMe,
                          HttpSession session,
                          HttpServletResponse response){
        AjaxResult result = new AjaxResult();
        Map<String, String> mapParam = new HashMap<String, String>();
        mapParam.put("loginacct", login);
        mapParam.put("userpswd", MD5Util.digest(userpswd));
        mapParam.put("type", type);
        try {

            if("member".equals(type)){
                Member member = memberService.getMemberInfo(mapParam);
                session.setAttribute(ConstUtil.LOGIN_MEMBER, member);
                if(rememberMe){
                    String logincode = "\"loginacct="+member.getLoginacct()+"&userpwd="+member.getUserpswd()+"&logintype=member\"";
                    //loginacct=admin&userpwd=21232f297a57a5a743894a0e4a801fc3&logintype=1
                    System.out.println("用户-存放到Cookie中的键值对:logincode::::::::::::"+logincode);
                    Cookie c = new Cookie("logincode",logincode);
                    
                    c.setMaxAge(60*60*24*14); //2周时间Cookie过期     单位秒
                    c.setPath("/"); //表示任何请求路径都可以访问Cookie
                    
                    response.addCookie(c);
                }
            }else{
                User user = userService.getUserInfo(mapParam);
                session.setAttribute(ConstUtil.LOGIN_USER, user);
                if(rememberMe){
                    //服务器向客户端写Cookie时含有特殊符号,Tomcat7不需要增加双引号;Tomcat6需要增加双引号;
                    //否则将来服务器端可能读取不到Cookie值(logincode串)
                    String logincode = "\"loginacct="+user.getLoginacct()+"&userpwd="+
                                       user.getUserpswd()+"&logintype=user\"";
                    //loginacct=admin&userpwd=21232f297a57a5a743894a0e4a801fc3&logintype=1
                    System.out.println("用户-存放到Cookie中的键值对:logincode::::::::::::"+logincode);
                    Cookie c = new Cookie("logincode",logincode);
                    
                    c.setMaxAge(60*60*24*14); //2周时间Cookie过期     单位秒
                    c.setPath("/"); //表示任何请求路径都可以访问Cookie
                    
                    response.addCookie(c);
                }
                //----------------------------------
                List<Permission> permissionList = userService.getUserRolePermissionByUserId(user.getId());
                Permission permissionRoot = null;
                Set<String> uris = new HashSet<String>();
                Map<Integer,Permission> map = new HashMap<Integer,Permission>();
                for(Permission bean :permissionList){
                    map.put(bean.getId(), bean);
                    uris.add("/"+bean.getUrl());
                }
                for(Permission bean :permissionList){
                    Permission children = bean;
                    if(bean.getPid() == 0){
                        permissionRoot = bean;
                    }else{
                        Permission parent = map.get(children.getPid());
                        parent.getChildren().add(children);     
                    }
                }
                session.setAttribute(ConstUtil.PERMISSION_ROOT, permissionRoot);
                session.setAttribute(ConstUtil.URIS, uris);
                //----------------------------------
            }
            result.setData(type);
            result.setSuccess(true);
        } catch (Exception e) {
            
            e.printStackTrace();
            result.setMessage("登录失败!");
            result.setSuccess(false);
        }
                 
        return result;
        
    }
    //跳转到主页面
    @RequestMapping("/main")
    public String main(HttpSession session){

        return "main";
    }
    //跳转到主页面
    @RequestMapping("/member")
    public String member(HttpSession session){
        return "member/index";
    }
    //跳转到首页
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();//销毁session对象
        return "redirect:/index.htm";
    }
}

三、session

1、概念

服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession

2、快速入门

1. 获取HttpSession对象

HttpSession session = request.getSession();

2. 使用HttpSession对象:

Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)

3、 原理

Session的实现是依赖于Cookie的。

4、细节

1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
        * 默认情况下。不是。
        * 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
             Cookie c = new Cookie("JSESSIONID",session.getId());
             c.setMaxAge(60*60);
             response.addCookie(c);

    2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
        * 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
            * session的钝化:
                * 在服务器正常关闭之前,将session对象系列化到硬盘上
            * session的活化:
                * 在服务器启动后,将session文件转化为内存中的session对象即可。
            
    3. session什么时候被销毁?
        1. 服务器关闭
        2. session对象调用invalidate() 。
        3. session默认失效时间 30分钟
            选择性配置修改    
            <session-config>
                <session-timeout>30</session-timeout>
            </session-config>

5、session的特点

  1. session用于存储一次会话的多次请求的数据,存在服务器端
  2. session可以存储任意类型,任意大小的数据

6、session的创建和关闭

  • Session创建:在你打开一个浏览器开始访问的时候,就创建了。
  • Session关闭:他在你关闭浏览器的时候或者默认时间(Tomcat是30分钟)后会销毁。

7、session与Cookie的区别:

  1. session存储数据在服务器端,Cookie在客户端
  2. session没有数据大小限制,Cookie有
  3. session数据安全,Cookie相对于不安全

 

 

标签:java,String,Session,bean,session,Cookie,import,cookie
来源: https://www.cnblogs.com/konglxblog/p/15322178.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有