导言:
一:会话技术,用户访问浏览器访问web服务器的资源,就是一次会话,会话技术的两端,分别是浏览器和服务器,直到任何一方断开连接,会话结束.一次会话可以有多次请求和响应
二:会话跟踪,一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在一次会话的多次请求中共享数据
三:会话跟踪方案有三种,cookie,session,jwt令牌
1.客户端会话技术cookie,浏览器第一次访问web服务器的时候,会在服务器生成一个cookie,里面可以存储当前用户的信息,如用户名以及Id,然后服务器在响应数据的时候自动把cookie响应给浏览器,浏览器再自动把cookie存储到浏览器本地,后续的每一次浏览器请求中,都会自动把cookie传递给服务器,服务器再来判断这个cookie是否存在
优点:HTTP协议支持这个技术
缺点:移动端APP无法使用这个技术
用户可以自己在浏览器设置中,禁用这个技术
Cookie不能跨域,跨域有三个维度:协议,IP/域名,端口,这三个维度只要有一个不同就是跨域
2.服务端会话跟踪技术session,底层其实就是cookie,和cookie不同的是,服务器会把session存储到服务器本地,再把session响应给浏览器
优点:存储在服务器,更加安全
缺点:cookie技术的缺点,都有
我们现在的技术一般都不会只有一台服务器,因为一台服务器容易引发单点故障,所以现在企业应用中,都是以集群的形式部署服务器,用户在访问的时候会访问负载均衡服务器,这个服务器在把浏览器的请求均匀的部署到tomcat服务器中,因为session是存储在服务器中,所以在集群部署的服务器模式中无法直接使用这个技术
3.jwt令牌,本质其实就是一个字符串
优点:可以存储到PC端,移动端,小程序端
可以部署到服务器集群环境,因为jwt令牌并不存储在服务器端中
减轻服务器端存储的压力
缺点:需要自己实现
一:基于interceptor拦截器进行登录校验
是一种动态拦截方法的机制,类似filter过滤器,由spring提供,用来动态拦截控制器方法的执行
可以在执行指定方法的前中后拦截请求,并进行我们预设的逻辑代码
浏览器发送请求给DispatcherServlet(前端控制器),前端控制器接收请求并调用 HandlerMapping处理器映射器,处理器映射器根据具体请求url,生成处理器对象,及处理器拦截器返回给DispatcherServlet,在DispatcherServlet调用HandleAdapter处理器适配器执行处理器controller前,拦截器可以进行相关的登录校验
1.定义一个拦截器,实现HandleInterceptor这个接口,并重写所有方法,preHandle,postHandle, afterCompletion,登录校验的逻辑代码就在preHandle方法体中,如果为true就放行,如果为false,校验失败,无法访问下一步资源
2.注册拦截器,定义一个配置类去实现WebMvcConfigurer接口,并重写addInterceptors这个方法,把拦截器对象,以及要执行的拦截哪些路径,注册到拦截器中
二:如何生成一个jwt令牌
jwt令牌由三部分组成,第一部分header(头),记录签名算法,令牌类型等,第二部分PayLoad(有效载荷),可以携带自定义信息,第三部分signature(签名),防止token被篡改,确保安全性
1.导依赖,jjwt
2.生成一个jwt令牌:
Jwts.builder() .addClaims(claims) //第二部分,自定义载荷内容,形参是一个Map集合 .signWith(SignatureAlgorithm.HS256, signKey) //签名算法+指定秘钥 .setExpiration(new Date(System.currentTimeMillis() + expire)) //过期时间 .compact();
三:在拦截器的第一个方法preHandle中进行校验
1.判断请求路径是否是login,如果是第一次登录,就放行
2.如果不是登录请求,判断请求头token的jwt令牌是否合法
3.先判断是否为空,为空直接返回false,不为空进行下一步判断
4.解析jwt令牌,解析成功的标志就是不报错,就返回true,放行,解析失败报错,就返回false,登录失败,无法访问下一步的web资源
解析jwt令牌方法:
Jwts.parser() .setSigningKey(signKey) .parseClaimsJws(jwt) .getBody();
四:在原有loginController的登录请求中改造
原有的方法是,前端把用户登录的登录名和密码传给controller层,我们去根据这个用户名和密码在数据库中查找,如果在数据库中有这个用户名和密码,返回相应的实体类对象,如果没有,返回的实体类对象为空
进行判断,如果这个实体类对象不为空,并且用户在执行登录操作,下发一个令牌,在jwt令牌的第二部分,自定义载荷claims中,把用户的ID,登录名,密码添加到这个Map集合中,并生成jwt令牌,如果为空,返回一个result结果,登录名或密码错误