状态保持问题:Cookie与Session

由于HTTP协议是无持续状态的协议,所以在 HTTP协议 实现会话状态保持是一个挑战,目前主要的做法是采用 Cookies 和 Session 技术解决。

HTTP协议是无持续状态的, 数据发送完毕,连接立即释放。 这种工作方式可以使用服务器的资源充分复用,可以为更多客户端服务。简称:无状态协议

无状态协议:由于服务器服务结束以后,释放了连接,不再与客户端保持状态, 无法记住客户端, 如: 客户是否登录过。

1、Cookies 技术

Cookies 技术,是在HTTP协议基础之上实现状态保持技术,其工作原理与会员卡类似:

  1. 在客户端第一次来访时候,发会员卡(cookie)。
  2. 服务端可以将信息记录到卡上。
  3. 客户端在每次来访时候, 都要带上会员卡用于识别身份。
  4. 状态信息记录在 会员卡 上。

Cookies 原理:

  1. 在浏览器第一次来访时候,发Cookies。
  2. 服务器可以将信息记录到Cookies上。
  3. 浏览器在每次来访时候, 都要带上Cookies用于识别身份。
  4. 状态信息记录在 Cookies 上。

Cookie 饼干,当年 Netscape 公司设计了一个无厘头名字。

Cookies的使用:

  1. Cookies 现在作为HTTP协议扩展功能,被浏览器广泛支持。
  2. Cookies 利用 HTTP 协议 消息头传送数据。
  3. Cookies 是一个HTTP协议扩展标准,其协议头是严格规定的。
  4. Java Servlet API 提供Cookies API,只需要使用这些API就能自动下发Cookies,自动获取上传Cookies。

Cookie中的特殊字符和中文

由于Cookie是在Http协议头部传送的, Http协议头必须是 ISO8859-1 编码,并且不能使用特殊字符和中文。

  1. 利用 Escape 编码进行解决,是HTTP协议标准。

  2. 数据加入Cookie之前进行编码即可。

  3. Java 提供了编码API

URLEncoder.encode(“您好Cookie”, “UTF-8”)

  1. 解码API

URLDecoder.decode(cookie.getValue(),“utf-8”)

Cookie的域名和路径

  1. 浏览器在保存Cookie时,每个网站保存一组对应Cookie,在发送时候发送到对应的网站。 根据域名区分不同的网站
  2. 同一个网站的Cookie按照路径分级存储,回传时候按照路径级别回传:
    1. 目录中可以收到当前目录的Cookie和上级目录的Cookie
  3. 下发Cookie时候,默认情况下按照当前目录层次保存Cookie,可以利用setPath属性设置Cookie的保存路径。

注意:

服务器下发的Cookie保存在浏览器的内存中。
不同浏览器属于不同的客户端,不同的客户端拿不到其他客户端下发的Cookie,一旦浏览器关闭就会默认清空Cookie,在不关闭浏览器的情况下,Cookie默认存活30min。
Cookie可以设置存活时间,一旦设置了存活时间Cookie就不再保存在浏览器内存中,而是保存在本地硬盘中,Cookie不会再因为浏览器的关闭而清空,可以利用Cookie来保存用户名,但不能用来保存密码!!!

cookie.setMaxAge(60);//以秒为单位

设置Cookie

public class SetCookie extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response){
        try {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Cookie cookie1= null;
        try {
            cookie1 = new Cookie("cookie1", URLEncoder.encode(" 你好cookie","utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Cookie cookie2=new Cookie("cookie2","hello cookie2");
        response.addCookie(cookie1);
        response.addCookie(cookie2);
    }
}

获取Cookie

public class getCookie extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response){
        try {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Cookie[] cookies=request.getCookies();
        for(int i=0;i<cookies.length;i++){
            try {
                System.out.println("name="+cookies[i].getName()+"  value="+ URLDecoder.decode(cookies[i].getValue(),"utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }
}

2、Session 原理

Cookie的问题

  1. 不安全,可以被冒用,涂改
  2. 不能存储大量信息,一般不超过4K
  3. 只能存储文本
  4. Cookie保存在客户端不安全,不能存储敏感信息,如: 密码·

Session 在Cookie基础之上解决了安全问题。

Session解决问题的方案类似于 银行卡!

  1. Session将数据存储在 服务器 端
  2. Session利用Cookie存储了一个 号码,用于识别用户身份,称为SessionID
  3. 服务端设置了一个集合,这个集合就是Session,并且与SessionID绑定
  4. 第一次创建Session时候,服务器创建Session集合对象并且分配Session的ID,将Session ID自动下发到 浏览器Cookie,浏览器关闭,Session中存储的数据也还存在,但重启浏览器后,由于之前的Cookie被清除,Session中的数据拿不到。
  5. 第二次请求时候浏览器通过Cookie传送回 SessionID,服务器会找到对应Session集合。 为用户提供存储服务。
  6. 当客户端SessionID丢失时或者浏览器离线以后,服务器会定时销毁Session。 默认是30分钟.

Java 提供了Session API

HttpSession session = request.getSession();-为什么是获取session,服务端设置了一个集合,这个集合就是Session,
session.setAttribute("message", "Hello World!");

设置Session

public class SetSession extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response){
        try {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        HttpSession session=request.getSession();
        session.setAttribute("message","你好Session");
    }
}

获取Session

public class getSession extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response){
        try {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        HttpSession session=request.getSession();
        String st=(String)session.getAttribute("session");
        System.out.println(st);
    }
}

利用Session与Cookie技术的登录案例:

业务逻辑:只有数据库中的用户才能有增删改查用户的权限,在进入用户管理界面前需要进行登录状态的验证,当处于已登录状态时,可以正常进入用户管理界面;未处于已登录状态时,需要跳转到登录窗口进行登录,在相应位置填好用户信息后点击登录按钮,将用户信息发送到后台,与数据库中用户信息进行比较,若能匹配上,设置Session,跳转回第一个界面,点击用户管理再次进行登录状态的验证;若匹配不上,返回登陆界面,提示用户名或密码错误。
在这里插入图片描述

验证登录:

  • 请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <h1><a href="user/ifLogin">用户管理</a></h1>
  </body>
</html>
  • web.xml
    <servlet>
        <servlet-name>ifLogin</servlet-name>
        <servlet-class>controller.IfLogin</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ifLogin</servlet-name>
        <url-pattern>/user/ifLogin</url-pattern>
    </servlet-mapping>
  • controller层
package controller;

import bean.User;

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

public class IfLogin extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session=request.getSession();
        User user= (User) session.getAttribute("user");
        String path=request.getContextPath();
        if(user==null){
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
            response.sendRedirect(path+"/user/getUsers");
        }
    }
}

实现登录

  • 登录界面
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%
        Cookie[] cookies=request.getCookies();
        for(Cookie cookie:cookies){
            if("name".equals(cookie.getName())){
                request.setAttribute("name", URLDecoder.decode(cookie.getValue(),"utf-8"));
            }
        }
    %>
</head>
<body>
${message}
<form action="login" method="get">
    用户名:<input type="text" name="name" value="${name}"><br>&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="password" name="password"><br>
    记住用户名<input type="checkbox" name="memory" value="1"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

  • web.xml
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.Login</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/user/login</url-pattern>
    </servlet-mapping>
  • controller层
package controller;

import bean.User;
import service.UserService;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.net.URLEncoder;

public class Login extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name=request.getParameter("name");
        String password=request.getParameter("password");
        int memory=Integer.parseInt(request.getParameter("memory"));
        HttpSession session=request.getSession();
        UserService userService=new UserService();
        User user=userService.findUserByNameAndPassword(name,password);
        if(memory==1){
            Cookie cookie=new Cookie("name", URLEncoder.encode(name,"utf-8"));
            cookie.setMaxAge(60*60);
            response.addCookie(cookie);//很容易忘!!!
        }
        if(user==null){
            request.setAttribute("message","用户名或密码错误");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
            System.out.println(user.toString());
            String path=request.getContextPath();
            session.setAttribute("user",user);
            response.sendRedirect(path+"/index.jsp");
        }
    }
}

  • service层
    public User findUserByNameAndPassword(String name, String password) {
        return userDao.findUserByNameAndPassword(name,password);
    }
  • dao层
    public User findUserByNameAndPassword(String name, String password) {
        User user=new User();
        Connection connection=DBUtil.getConnection();
        String sql="select * from user where name=? and password=?";
        PreparedStatement ps=null;
        try {
            ps=connection.prepareStatement(sql);
            ps.setString(1,name);
            ps.setString(2,password);
            ResultSet rs=ps.executeQuery();
            while(rs.next()){
                user.setName(rs.getString("name"));
                user.setPassword(rs.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection);
        }
        return null;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值