token的作用及实现原理(二,进阶知识)

前面已经说过关于Cookie和HttpSession,这两种保存会话数据的两种技术,今天在这里细说一下。
Cookie —只能存字符串,不能存对象
Cookie是客户端的技术,程序把每个用户的数据以Cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去,这样,web资源处理的就是用户自己的数据了。
HttpSession ----可存储对象。
HttpSession是服务端的技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个独享的HttpSession对象,由于Session为用户自己浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据资源放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的Session中取出数据为用户服务。

Cookie和Session的区别:
Cookie : 是吧用户的数据写给用户的浏览器
Session : 是把用户的数据写到用户独占的session中。session对象是由服务器创建,可以由reqest.getSession方法得到session。
关联:sessionID本身放到session中去,同时也会复制一份给JSsessionID,因此这个两者是一样的(其实我们去验证就是将两者匹配)


Cookie API----浏览器应该支持每台web服务器又20个cookie,总共300个cookie,并且每一个cookie 的大小限定为4KB。
Cookie是客户端的技术,是因为Cookie数据是由客服端来保存和携带的,所以被称为客户端的技术
所在位置:javax.servlet.http.Cookie,该类的是这么定义的:public class Cookie implements Cloneable, Serializable,里面定义了很多的方法 , 源码如下:(Cookie属性)

public class Cookie implements Cloneable, Serializable {
private static final CookieNameValidator validation;
private static final long serialVersionUID = 1L;
private final String name;
private String value;

static {
    String prop = System
            .getProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");
    boolean strictNaming;
    boolean strictNaming;
    if (prop != null) {
        strictNaming = Boolean.parseBoolean(prop);
    } else {
        strictNaming = Boolean
                .getBoolean("org.apache.catalina.STRICT_SERVLET_COMPLIANCE");
    }
    if (strictNaming) {
        validation = new RFC2109Validator();
    } else {
        validation = new NetscapeValidator();
    }
}

private int version = 0;
private String comment;
private String domain;
private int maxAge = -1;
private String path;
private boolean secure;
private boolean httpOnly;

public Cookie(String name, String value) {
    validation.validate(name);
    this.name = name;
    this.value = value;
}

public void setComment(String purpose) { // 设置Cookie的用处说明。浏览器显示Cookie信息的时候显示该说明。
    this.comment = purpose;
}

public String getComment() { //取得Cookie的用处说明,览器显示Cookie信息的时候显示该说明。
    return this.comment;
}

public void setDomain(String pattern) {  // 设置该Cookie的域名
    this.domain = pattern.toLowerCase(Locale.ENGLISH);
}

public String getDomain() { // 可以访问该Cookie的域名。如果设置为”.google.com”,则所有以”google.com”结尾的域名都可以访问该Cookie。
注意第一个字符必须为“.”
    return this.domain;
}

/**
*MaxAge,负数:cookie的数据存在浏览器缓存中。0 :删除,删除时路径要不保持一致,否则删错。正数:缓存的时间。
*这里需要注意一点:设置为0删除,设置该项之前,必须确定删除cookie的路径。
*/
public void setMaxAge(int expiry) { // 正值表示cookie将在经过该值数秒后过期。注意,该值是cookie过期的最大生存时间,不是cookie当前时间。
    this.maxAge = expiry;					// 负值意味着cookie将不会被持久存储,将在web浏览器退出时,删除。0值将会导致删除cookie.
}

public int getMaxAge() {  //  cookie以秒为单位的指定Cookie的最大生存时间 ,默认为 -1指示该cookie将保存到浏览器关闭为止。
    return this.maxAge;
}

public void setPath(String uri) { // 设置cookie的路径
    this.path = uri;
}

public String getPath() { // 获取cookie路径
    return this.path;
}

public void setSecure(boolean flag) { // 该Cookie是设置否仅被使用安全协议传输。安全协议有HTTPS,SSL等。但是不具有加密,如果想要加密自己写
    this.secure = flag;
}

public boolean getSecure() { // 取得
    return this.secure;
}

public String getName() {  // 取得该Cookie的名称
    return this.name;
}

public void setValue(String newValue) {  //设置该Cookie的值
    this.value = newValue;
}

public String getValue() { // 取得该Cookie的值
    return this.value;
}

public int getVersion() { // 拿到该Cookie使用的版本号
    return this.version;
}

public void setVersion(int v) { // 设置该Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC2109规范
    this.version = v;
}

public Object clone() { // 克隆方法
    try {
        return super.clone();
    } catch (CloneNotSupportedException e) {
        throw new RuntimeException(e);
    }
}

public void setHttpOnly(boolean httpOnly) { // 如果在Cookie中设置了"HttpOnly"属性,那么通过JavaScript脚本将无法读取到Cookie信息,
// 这样能有效的防止XSS攻击,让网站应用更加安全。
    this.httpOnly = httpOnly;
}

public boolean isHttpOnly() {
    return this.httpOnly;
}
}

在这个包下,org.apache.catalina.connector.Response;里面有一个addCookie()方法,用于在响应头增加一个相应的Set-Cookie头字段。

public void addCookie(Cookie cookie) {
    if ((this.included) || (isCommitted())) {
        return;
    }
    String header = generateCookieString(cookie);

    addHeader("Set-Cookie", header, getContext().getCookieProcessor()
            .getCharset());
}

在org.apache.catalina.connector.Request;里面有个getCookies()方法,用于获取客户端提交的Cookie.

public Cookie[] getCookies() {
    if (!this.cookiesConverted) {
        convertCookies();
    }
    return this.cookies;
}

具体例子:(下面是为了说明问题,不可运行)

package com.dialog.test;

import javax.servlet.http.Cookie;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

public class TestDialog {
	public static void main(String[] args) {
    Cookie cookie = new Cookie("zhouyi", "");

    Response response = new Response();
    response.addCookie(cookie);
    Request request = new Request();
    request.getCookies();
}
}

cookie禁用问题的解决方式:1,给出提示,开启cookie ; 2 , URL重写,必须对网站的所有地址重写。

HttpSession API
问题抛出:我们浏览网页,比如买东西的历史纪录,总是给出最新的历史纪录。是如何做到,存的显然是对象,
这时候就可以利用session对象,一个浏览器独占一格session对象。(购物车的实现以及登陆验证,待写)。

定义如是:javax.servlet.http.HttpSession;源码如下:

public abstract interface HttpSession {
public abstract long getCreationTime(); // 获取session创建时间,是格林尼治时间。

public abstract String getId(); // 获取sessionID

public abstract long getLastAccessedTime(); // 获得最后一次访问session的时间。

public abstract ServletContext getServletContext(); // 获取Servlet上下文,已经废弃

public abstract void setMaxInactiveInterval(int paramInt); // 设置session的有效时间,有生命周期的

public abstract int getMaxInactiveInterval(); // 获取session的有效时间

/**
 * @deprecated
 */
public abstract HttpSessionContext getSessionContext(); // 返回 session 在其中得以保持的环境变量。 这个方法和其他所有
// HttpSessionContext 的方法一样被取消了。

public abstract Object getAttribute(String paramString); // 设置单个属性

/**
 * @deprecated
 */
public abstract Object getValue(String paramString); // 根据name拿到value值,已经废弃

public abstract Enumeration<String> getAttributeNames(); // 获得多个name属性

/**
 * @deprecated
 */
public abstract String[] getValueNames();  // 拿到多个value值,已经废弃

public abstract void setAttribute(String paramString, Object paramObject); // 设置

/**
 * @deprecated
 */
public abstract void putValue(String paramString, Object paramObject);// 已经废弃

public abstract void removeAttribute(String paramString); // 移除name

/**
 * @deprecated
 */
public abstract void removeValue(String paramString); // 移除value,已经废弃

public abstract void invalidate(); // 使session销毁,默认自动销毁30分钟。也可以使用配置文件设置销毁时间

public abstract boolean isNew(); // 返回一个布尔值以判断这个 session 是不是新的
}

在org.apache.catalina.connector.Request;中有getSession方法。

 public HttpSession getSession() {
    Session session = doGetSession(true);
    if (session == null) {
        return null;
    }
    return session.getSession();
}

getSession()执行原理:
1,获取名称为JSESSIONID的cookie值
2,如果没有这样的cookie,创建一个新的HttpSession对象,分配一个唯一的SessionID。并向客服端编写一个名字为JSESSIONID = SessionID的cookie.
3,如果有这样的cookie,获取cookie的值(即HttpSession对象的值),从服务器的内存中根据ID找到那个HttpSession对象:找到了,取出继续为您服务。若早不到,回到2重新开始。

getSession(boolean create): 参数为true和上面一样;参数为false,根据JSESSIONID的cookie值,找到对应的HttpSession对象,找不到则返回null,这个不会创建新的,只是起了查询的作用。
(使用Session实现一次性验证码,待写(一中已经写过一部分))

测试例子:

  @RequestMapping("/testCookieAndSession")
@ResponseBody
  public String testCookieAndSession(HttpServletResponse response,HttpServletRequest request,HttpSession session) {
  response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // 错误500 (Internal Server Error)解决方案
  response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
  response.setHeader("Access-Control-Max-Age", "3600");
  response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
  response.setHeader("Access-Control-Allow-Credentials","true");
  response.setContentType("application/json");
  response.addCookie(new Cookie("zhouyi", "18329jdd"));
  TestUser usr = new TestUser();
  usr.setTestUserNo(123);
  usr.setTestUserName("周毅");
  usr.setTestUserSex("男");
  session.setAttribute("TestUser", usr);
  return "cookie";
  }

postman结果和网页访问结果:
在这里插入图片描述
网页:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值