zoukankan      html  css  js  c++  java
  • Servlet之会话(Session)以及会话追踪技术(Cookie),(URL重写)和(隐藏表单域)

    Session

    什么是会话?

    会话:

    Web应用中的会话 指的是一个客户端浏览器与Web服务器之间连续发生的一系列请求和响应的过程

    会话状态:

    Web服务器和浏览器在会话的过程中产生的状态信息

    作用:

    借助会话的状态,web服务器能够把同一个会话中的一系列的请求和响应过程关联起来,使得他们之间可以相互依赖和传递信息

    创建会话:

    HttpservletRequest 中建立会话:

    • HttpSession getSession()
      是否之前有建立Session,如果没有,创建一个Session,如果有,使用当前Session

    • HttpSession getSession(boolean create)
      是否之前有建立Session,如果有,使用当前Session
      如果没有,看参数值:
      true 创建一个新的session
      false 不创建,返回null


    HttpSession 常用方法

    boolean isNew()  // 判断该会话是否是一个新创建的Session
    
    long getCreationTime()   //获取该Session创建的时间 毫秒值 1/1/1970 
    
    java.lang.String getId()   //Session的ID值,不重复
    
    long getLastAccessedTime()  // 获得最后一次访问此会话的时间  毫秒值 1/1/1970 
    
    int getMaxInactiveInterval()   //获取会话超时的最大时间值  秒值
    
    java.lang.Object getAttribute(java.lang.String name)
    
    void setAttribute(java.lang.String name,java.lang.Object value)
    

    如何实现有状态的会话

    HTTP协议是一种无状态的协议:浏览器主动发出一个请求,web服务器被动的回应一个结果。不会保留客户的任何信息。

    服务器接收到某个浏览器的访问请求,无法确定该浏览器之前所访问的请求信息。

    使用会话ID(SessionID)来标识每次请求信息以实现由状态的会话

    常用的会话跟踪技术:

    1 通过Cookie在请求消息中进行传递会话ID

    2 通过URL重写 使用请求URL把会话ID作为参数传给服务器

    什么是Cookie?

    在浏览器访问Web服务器的某个资源的时候,由Web服务器在HTTP响应消息头中附带传给浏览器的一段数据
    浏览器可以决定是否保存这段数据
    一旦数据保存,在以后每次访问该web服务器的时候,都会在HTTTP请求都中将这段数据传给Web服务器

    Cookie响应字段

    服务器通过设置响应消息头中的Cookie来发送SessionID
    
    设置Cookie的方式:
    
    Set-Cookie:Name=value;Domain=xx;max-age=seconds;path=path;
    
    说明:
    
    	name:指定cookie的名称
    
    	value: 指定cookie名称的值
    
    	Domain: 指定Cookie在哪个域中有效,浏览器访问这个域中所有的主机的时候,都想会使用这个Cookie信息
    
    	Max-age:指定Cookie在客户端保存的有效时间(秒)
    
    		正数:保存在客户端文件系统中的时间
    
    		0: 通过浏览器立即删除这个Cookie
    
    		负数: 在浏览器中关闭的时候删除这个Cookie
    
    	
    	Path:用于指定Cookie对服务器上的哪个URL目录及其子目录有效
    

    Cookie常用方法:

    构造方法:
    
    public Cookie(java.lang.String name,java.lang.String value)
    
    普通方法:
    
    getName();
    
    getValue()/setValue(String value);
    
    getMaxAge() / setMaxAge(int age)
    
    setPath(String uri)
    
    • 服务器端Servlet发送Cookie到客户端
      使用HttpServletResponse 提供一个 void addCookie(Cookie cookie) 方法

    • 客户端发送Cookie到服务器端 自动发送 不需要调用方法

    • 服务器端获取客户发送的Cookie

      HttpServletRequest中 Cookie[] getCookies() 方法来获取客户端发送的所有 Cookie


    下面着两个代码演示Cookie中常用的方法:

    //SetCookie.java
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class SetCookie extends HttpServlet {
    	private static final long serialVersionUID = 1L;
       
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		HttpSession session = request.getSession();
    		
    		Cookie cookie = new Cookie("sessionID",session.getId());
    		cookie.setMaxAge(session.getMaxInactiveInterval());
    		cookie.setPath(request.getContextPath());
    		response.addCookie(cookie);
    		
    		response.setContentType("text/html;charset=utf-8");
    		response.getWriter().println("cookie已经发送");
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	
    		doGet(request, response);
    	}
    
    }
    
    
    //GetCookie.java
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class GetCookie extends HttpServlet {
    	private static final long serialVersionUID = 1L;
     
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		request.getSession();
    		response.setContentType("text/html;charset=utf-8");
    		Cookie[] cookies =request.getCookies();
    		for(int i=0;i<cookies.length;i++) {
    			response.getWriter().println("获取到的cookie信息:<br/>");
    			response.getWriter().println(cookies[i].getName()+"<br/>");
    			response.getWriter().println(cookies[i].getValue()+"<br/>");
    			response.getWriter().println(cookies[i].getMaxAge()+"<br/>");
    			response.getWriter().println(cookies[i].getPath()+"<br/>");
    		}
    		
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		doGet(request, response);
    	}
    
    }
    
    

    然而这两段代码的执行结果却如图所示:

    上面的代码获取到了两个Cookie的记录,是因为当我们访问的时候 web服务器会自动给我们一个名为JSESSIONID的Cookie,而我们在第一个.Java文件中又设置了一个Cookie,因此我们便获得了2个Cookie。但是为甚么我们getMaxAge的结果为-1 getPath的结果为null呢?

    在javax.servlet.http.Cookie源码中:

    public Cookie(String name, String value) {
            if (name == null || name.length() == 0) {
                throw new IllegalArgumentException(
                        lStrings.getString("err.cookie_name_blank"));
            }
            if (!isToken(name) ||
                    name.equalsIgnoreCase("Comment") || // rfc2019
                    name.equalsIgnoreCase("Discard") || // 2019++
                    name.equalsIgnoreCase("Domain") ||
                    name.equalsIgnoreCase("Expires") || // (old cookies)
                    name.equalsIgnoreCase("Max-Age") || // rfc2019
                    name.equalsIgnoreCase("Path") ||
                    name.equalsIgnoreCase("Secure") ||
                    name.equalsIgnoreCase("Version") ||
                    name.startsWith("$")) {
                String errMsg = lStrings.getString("err.cookie_name_is_token");
                Object[] errArgs = new Object[1];
                errArgs[0] = name;
                errMsg = MessageFormat.format(errMsg, errArgs);
                throw new IllegalArgumentException(errMsg);
            }
    
            this.name = name;
            this.value = value;
        }
    
    

    所以getPath等方法是在创建cookie传给浏览器前使用的,从浏览器传到后台时只有name和value


    url重写

    Cookie被证明存在一些安全隐患,所以很多用户比较排斥这种方式。只能使用URL重写

    URL重写原理

      当服务器程序调用request.getSession();代码时,其会先看 request.getCookies()方法中有没有名为JSESSIONID的cookie带过来,如果没有,就看URL有没有被重写(即附带 JSESSIONID),如果有,则从服务器中找key为JSESSIONID的session对象,如果都没有,则创建一个新的session。如果用户禁用了cookie,则只能通过URL重写方式实现会话跟踪!
      其类似于get方式将信息追加到url后面
    注意
      每个页面都必须使用servlet或jsp动态生成(动态页面)。因为附加在URL上的sessionID是动态产生,所以对于静态页面的跳转,URL重写机制无能为力。
    即使使用动态页面,如果用户离开了会话并且通过书签或链接再次回来,会话信息也会丢失,因为存储下来的链接含有错误的标识信息。
    因此:
      必须将所有发送到客户端的url进行编码,调用HttpServletResponse接口中的encodeURL()方法和 encodeRedirectURL()方法来实现。在调用sendRedirect()方法之前使用encodeRedirectURL()方法。

    隐藏表单域

      只能用于特定操作中。仅当每个页面都由表单提交而动态生成的时候,才可以使用隐藏表单域,用来存储相关会话信息。
      它是一种最简单的方式,将字段隐藏在HTML表单中,但不在客户端显示。比如在第一张页面中输入用户名和密码登陆,服务器生成响应返回第二张页面。当第二张页面提交时可能仍然需要知道来自第一张页面中的用户名。
      那么就可以通过隐藏表单域来实现这一连续的过程。当第一张页面提交后,服务器端作出响应返回第二张页面,此页面中用隐藏域记录了来自登陆时的用户名。通俗说就是当服务器回发给客户端的响应中,就同时把用户名再次回发到客户端,用隐藏域隐藏起来,是不可见的。当第二张页面提交时,此隐藏域中的用户名一并随表单提交。这样服务器就仍然可以判断此用户是否与以前的用户相同。于是,再次处理完结果后继续将响应回发给客户端,且此响应中也仍然包含了用户名,在客户端中仍然用隐藏域将这一信息隐藏。
      这样就完成了一个连续请求的动作,但是对于用户,这是不可见的。

  • 相关阅读:
    Express ejs 3.* layout.ejs
    old header
    mac 命令行 安装 需要管理员 权限
    Understanding the Debug Log
    insufficient_access_on_cross_reference_entity APEX / Salesforce
    custom list view
    exam help
    Backbone.js Wine Cellar 教程
    理解RESTful架构
    SpringCloud入门之应用程序上下文服务(Spring Cloud Context)详解
  • 原文地址:https://www.cnblogs.com/nm666/p/7967261.html
Copyright © 2011-2022 走看看