Fork me on GitHub

java基础之----cookie,session,jwt

概要

web中为什么要引入cookie、session机制,为了验证用户的身份,验证用户的身份是为了系统的安全,那如果是系统和系统之间的API调用怎么办呢?因为系统之间调用往往是没有用户系统的(用户系统就是使用用户名,密码机制),这时就出现了JWT,下面详细说明cookie,session,JWT的流程,原理和代码演示。

cookie,session机制原理

首先,cookie是浏览器保存的,session是服务器保存的,那cookie和session有什么关系呢?如下,当用户首次访问的时候,服务器会为用户的这次会话建立一个session,每个session都有一个独立的session id,当服务器响应浏览器的时候会把这个sessionid返回到浏览器,返回到浏览器放到哪里呢,放到cookie中,为什么要放到cookie中呢?因为用户下次再访问这个网站的时候需要把这个session id放到请求参数中,也就是说这个cookie是每次用户访问服务器都要带上的。

session超时的问题?

用户每次访问服务器,服务端都会自动为session超时时间续签,session默认的超时时间是30分钟。

session共享的问题?

如果服务端只有一个节点,就不存在共享问题,只有当服务端部署成分布式,才会有session共享的问题,那怎么实现session共享呢?目前主流的做法是使用redis把session缓存起来,所有节点每次都读取这个session就实现了session共享,spring-session已经把这种方式集成进来,后续会有例子。

JWT原理

jwt的验证一般来说是无状态的,什么叫无状态呢?在cookie-session机制中,服务器需要保存session,这种就是有状态的,而jwt机制,服务器不会保存这种信息,那jwt怎么实现权限认证呢?要弄清楚这个问题,需要先搞清楚jwt的组成,jwt由3部分组成,分别为:header(头部)、payload(载荷)、signature(签名),下面举个例子介绍这3个东东是什么。

header往往是这个样子:

{
"alg": "HS256",
"typ": "JWT"
}

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。

最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。

payload往往是这个样子:

{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

这个 JSON 对象也要使用 Base64URL 算法转成字符串。

signature往往这样子:

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

 

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

 

代码示例

session-cookie机制的基本使用方法:

@Controller
public class CookieTest {

    @ResponseBody
    @RequestMapping(value = "/get",method = RequestMethod.GET)
    public String test(HttpSession session){
        String value = String.valueOf(session.getAttribute("g"));
        System.out.println(value);
        return "cookie";
    }

    @ResponseBody
    @RequestMapping(value = "/add",method = RequestMethod.GET)
    public String cookieTest(HttpServletResponse response, HttpSession session){
        Cookie cookie= new Cookie("asdf","asfd");
        response.addCookie(cookie);
        session.setAttribute("g","niubi");
        session.setMaxInactiveInterval(2000);
        return "cookie";
    }
}

spring-session的基本使用

引入依赖

<dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
</dependency>

配置yml文件(先在本地安装redis,之后启动redis-server)

spring:
  redis:
    host: localhost
    database: 0
    port: 6379
    lettuce:
      pool:
        min-idle: 5
        max-idle: 8
        max-active: 8
        max-wait: 1ms
      shutdown-timeout: 100ms

代码测试

@RestController
public class SessionTest {



    @RequestMapping("/set")
    String set(HttpServletRequest req, HttpServletResponse response) {
        req.getSession().setAttribute("testKey","niubi");
        return "设置session:testKey=niubi";
    }


    @RequestMapping("/query")
    String query(HttpServletRequest req) {
        Object value = req.getSession().getAttribute("testKey");
        return "查询Session:\"testKey\"=" + value;
    }
}

在请求完set方法之后可以去redis中看一下,会发现多出了三个key,有兴趣的可以了解一下每个key的作用,参考这篇文章

jwt基本使用

看这个大佬的例子:https://github.com/hyrepo/jwt-demo

 

参考文章:

http://blog.didispace.com/tags/Spring-Session/

http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

https://github.com/hyrepo/jwt-demo

posted @ 2019-12-19 20:41  猿起缘灭  阅读(845)  评论(0编辑  收藏  举报