会话技术(会话、会话跟踪[Cookie、Session、JWT令牌技术])


会话技术

会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接·,会话结束。再一次会话中可以包含多次请求和响应。
(也可以理解为:一个IP地址所进行访问web服务器的资源,只要双方都不断开连接会话一直进行,但只要有一方断开连接就会自动断开此次会话)

会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求之间共享数据
会话跟踪的方案:
1、客户端会话跟踪技术:Cookie
2、服务端会话跟踪技术:Session
3、令牌技术

注意

为什么要使用会话跟踪?
因为先在的网站请求/响应多数都是遵守HTTP协议的,所以这样子会使得在请求服务器或者响应是无状态的,会给我们带来了许多的便捷,但是正是因为无状态,不可以在同一次会话的多次请求之间共享数据
什么是共享数据?
就是在同一次会话的请求之间所携带的数据进行共享

一、客户端会话跟踪技术:Cookie

概念

优点
HTTP协议中支持的技术
此优点所带来的好处;
三个自动
服务器会自动的将Cookie响应给浏览器,
浏览器会自动的将Cookie存储在浏览器本地,
在后续的请求中浏览器会自动的携带Cookie进行请求。
他会带来一个响应头(Set-Cookie)和一个请求头(Cookie)
响应头(Set-Cookie)
HTTP响应头被用于从服务器向用户代理发送cookie。
请求头(Cookie)
HTTP请求头包含存储嫌弃那通过与所述服务器发送的Set-Cookie头。

缺点
1、移动端APP无法使用Cookie
2、不安全,用户可以自己禁用Cookie
3、Cookie不能跨域
什么是跨域
在浏览器进行访问时会向前端地址进行访问,然而在需要向服务器进行传递时若发现服务器与前端地址的IP/域名、端口不一样,此时在进行访问的话就相当于是跨域访问了。
跨域可以直接理解为:三个维度(协议、IP/域名、端口)

代码演示

这里的是直接在SpringBoot的控制层进行写入代码进行实现

//    设置Cookie
    @GetMapping("/c1")
    public Result cookiel(HttpServletResponse response){
        response.addCookie(new Cookie("login_username","itheima"));//设置Cookie/响应Cookie
        return Result.success();
    }

//    获取Cookie
    @GetMapping("/c2")
    public Result cookiel2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();//获取所有的Cookie
        for (Cookie cookie : cookies){
            if (cookie.getName().equals("login_username")){//获取Cookie的name为:login_username的值
                log.info("login_username: {}",cookie.getValue());
            }
        }在这里插入图片描述

        return Result.success();
    }

**执行“/c1”**可以在响应头中看到客户端所响应的Set Cookie
在这里插入图片描述
**执行“/c2”**可以在请求头中看到客户端所响应的Cookie
在这里插入图片描述

有上述代码演示以及上述的图片,可以看到了数据的共享

二、服务度爱你会话跟踪技术:Session

概念:

Session是基于Cookie进行优化的一个会话跟踪方案。
优化原理:将Cookie的name固定设置为:jsessionid,而value的值将会随机ID(一组随机的字符串),凭借这个ID就可以向服务端进行此次会话数据的共享

优点
cookie的value存储在服务端,且更加的安全
因为此时的Cookie的value值是Session会话随机生成的ID,并不会直接将数据暴露在客户端,所以相对于Cookie会话更加的安全。

缺点
1、移动端APP无法使用Cookie
2、Cookie不能跨域
3、服务器集群环境下无法直接使用Session
问题一:
什么是服务器集群环境?
简单地说,集群 就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的 计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器。这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理。当用户请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器。
举个例子:
打开谷歌,百度的页面,看起来好简单,也许你觉得用几分钟就可以制作出相似的网页,而实际上,这个页面的背后是由成千上万台服务器集群协同工作的结果。

参考资料链接

问题二:
为什么服务器集群环境下无法直接使用Session?
因为使用Session会话时,服务器会自动生成一个Session ID,然而当服务器1已经对此次会话生成了一个Session ID,当客户端携带此ID向服务器2进行访问时,会发现服务器2,并没有此ID,所以无法使用Session会话。

代码演示

//     向HttpSession中存储值
    @GetMapping("/s1")
    public Result sessionl(HttpSession session){
        log.info("HttpSession-s1: {}",session.hashCode());

        session.setAttribute("loginUser","tom");//向session中存储数据
        return Result.success();
    }
//    从HttpSession中获取值
    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}",session.hashCode());

        Object loginUser = session.getAttribute("loginUser");//从session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
    }

**执行“/s1”**可以在响应头中看到客户端中生成的Session ID

在这里插入图片描述

**执行“/s1”**可以在请求头中看到客户端中生成的Session ID
在这里插入图片描述

有上述代码演示以及上述的图片,可以看到了数据的共享

三、JWT令牌技术

概念:

简介:JWT(全称:JSON Web Token
定义了一种简洁的、自包含的格式,用于在通讯双方以json数据格式安全的传输信息。
(由于数字签名的存在,这些信息是可靠且安全的)
自包含:一个组件能够独立地进行编译,不依赖于其他组件的特定包含顺序

JWT令牌的组成:

  1. 第一部分:Header(头),记录令牌的类型,签名的算法等。列如:{"atg":"HS256","type":"jwt"}
  2. 第二部分:Payload(有效负载),携带一些自定义的信息,默认信息等。列如:{"id":"2","username":"Tom","exp": 1730722706}
  3. 第三部分:Signature(签名),防止Token被篡改,确保安全性。将header、payload,并加入秘钥,通过指定的签名的算法而来

注意
1、JWT令牌每一个部分都是以".“来进行分割
2、JWT令牌在请求头中的存储数据为:
Header 头:eyJhbGciOiJIUzI1NiJ9.
Payload(有效负载):eyJuYW1lIjpudWxsLCJJZCI6MCwiZXhwIjoxNzMwNzIyNzA2LCJ1c2VybmFtZSI6ImNoeWIyIn0.
Signature(签名)tLWilH7eo5tn3k21bb5_o-1KYrV6wOVNhicMLoWDi2E
到这里可能会有疑问为什么会是这种毫无规律的一串字符串?
其实是因为JWT令牌会将Header头与Payload两部分使用Base64编码的形式进行编码,之后在以”."符号进行连接。
至于Signature(签名) 是使用了 JWT中的某个算法再加上**秘钥(此秘钥是自己设置的一长串字符串)**这样着更加的保证了数据的安全。

优缺点

优点
支持PC端、移动端
解决了集群环境下的认证问题
减轻服务器端存储的压力
缺点
需要自己实现

JWT的使用(场景:登录认证)

一、登陆成功后,生成令牌

概念:当登录成功之后,为了方便我们一般会先给前端发送一个JWT令牌,之后的对话中只携带此令牌就不需要在去登录。

代码实现

1、导入依赖

注意:在实现代码之前我们需要先去导入两个依赖:jjwt、jaxb-api

<!--		jwt令牌-->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
		</dependency>
<!--		jaxb-api-->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.1</version>
		</dependency>

2、调用方法,生成令牌

        String s = "360ede5c9fc444a2ac43f6821008d4c1";//秘钥
        String jwt = Jwts.builder()//调用此方法来进生成Jwt令牌
                .signWith(SignatureAlgorithm.HS256,s)//设置JWT中的某个算法,以及添加秘钥
                .setClaims(claims)//设置自定义的数据列如:{“Id”:1,"name":"残花月伴"}
                .setExpiration(new Date(System.currentTimeMillis() + 12*3600*1000))//设置JWT令牌有效时间,(当前时间+num毫秒)
                .compact();
        System.out.println("生成的Jwt为:"+jwt);

3、将生成好的令牌,传给前端

这里就直接一Json格式的形式进行返回前端即可,剩下的就交给前端了,

注意:当传给前端之后,前端会将此次会话的每一次请求都会携带此令牌,一般会将他进行封装到一个名叫“Token”的请求头中,
列如:在这里插入图片描述
而这时就需要去校验令牌是否是正确。

二、校验令牌

概念:在校验令牌之前我们需要知道如何判断此令牌是否正确,这就要去解析Jwt

  • 解析Jwt:
  • 解析之前我们需要拿到两个变量:一个是Jwt,一个是此令牌的秘钥
  • 代码演示:
        Claims claims = Jwts.parser()//调用解析Jwt的方法
                .setSigningKey("360ede5c9fc444a2ac43f6821008d4c1")//传递秘钥
                .parseClaimsJws(jwt)//传递Jwt的值
                .getBody();
        System.out.println(claims);

如何校验令牌:

方法一: 使用 过滤器(Fiter) 将令牌无效的请求进行过滤掉
方法二: 使用拦截器将令牌无效的请求进行拦截

这里因为内容排版问题过滤器(Fiter)拦截器(Interceptor)
大家可以看我下一章的内容(过滤器(Fiter)拦截器(Interceptor)


资料来源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值