布式Session跨域之JWT

面试必问之分布式Session跨域之JWT单点登录

 

场景和需求

今天我们来讨论一下最简单的登录方案,那么首先请问一下各位同学,你们有没有在项目里面实现过登录你们分别实现过什么样的登录方案,这个大家有没有思考过?

对,大家反馈的答案都很棒。 那么首先我们在项目里面为什么实现登录呢?大家有没有思考过?其实登录功能就相当于一个大门,只有通过这个大门,才能够看到门里面的一些风景,从项目的角度来说就是需要确认这个人是否有资格或者说权限来访问我们的一些资源,比如说电商网站需要查询我的订单,查看我的某个订单的支付信息等等功能。那么这时候问题又来了,请问你们的系统,是不是在每一个功能调用前,是否都去校验一下用户名密码?是的请给老师扣1,不是的扣0。

ok,看来大家的系统都只要登录一次,就可以一直使用项目的很多功能。对吧,那么这是怎么做到的呢?相信大家都写过类似的代码:

public String login(HttpServletRequest request,UserInfo user){
        
    //调用数据库验证
    if(userService.login(user)){ //登录成功
        request.getSession().setAttribute("user",user);
    }
    
}

这是一个最简单的登录功能,那么我们登录成功以后,会把相关的用户信息保存到session里面。请问各位同学,为什么我已经登录成功了,进入这个大门了,我还需要将这个用户信息保存到session里面?大家有没有思考过这个问题,还是说别人这么玩,我也这么玩?

大家说的都非常有道理,那么老师这里总结一下,我们登录成功后session可以用来做这么两件事情:

1: 追踪用户(当需要用到用户信息不需要再去数据库查询)。

2: 后续操作确认是否有权限(权限框架做或者Filter)

在我们单机系统里面,将信息放到session里面不会产生其他的问题,那么如果将我们增加了机器,业务系统弄成一个集群,或者说部署成一个分布式的系统,这个时候放在session里面的信息,将怎么办?

 

这就涉及到了session跨域共享的问题,针对这个问题,现在有这么几种解决方案:

1:session sticky(粘滞) : 保证客户端的每一次请求,都落在同一个服务器上面。Nginx设置ip_hash可实现。

这种方式存在一定的问题,nginx必须是最前端的机器,否则得不到用户的真实ip, 如果后端又有分流的机器,也会导致相关的问题。

客户端请求的ip是动态的,对应的后端服务器出现故障等。

 

2:session copy(复制): 当客户端请求某一台服务器产生session时,其他机器同步复制保存这个session。 Tomcat内置的Session复制可直接实现。

这种方式也存在问题,session是存在内存中的,用户量越来越庞大会严重影响所有服务器性能。

 

3:session统一存储: 弄一个统一的session服务器,使用Spring-Session-Data-Redis基于Redis存储实现。

这样做也有不小的缺点,首先是单点问题,如果这个服务器宕机,那么所有的服务都是不可用的,所以这里必须做集群,会浪费服务器资源。还有一点是,每次验证都需要来这个服务器来查,会凭白增加一次网络开销,降低访问速度

 

第一种和第二种方案适用于比较小的集群,可以作为针对中小型的网站的解决方案。第三种方案比前两种更好,但是会存在一个小问题,当统一存储的容器出现波动,或者其他问题倒置重启,所有的session都会丢失。那么老师这边还提供了一种基于cookie保持回话全新的解决方案,那就是JWT(Json Web Token)。

以上内容控制在 10 - 15分钟。

 

方案: 首先我们来看另外一种基于Cookie的会话保持。单点登录方案

#

应用和原理 : 什么是JWT,什么业务场景使用JWT?

 

JWT: https://jwt.io/

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. JSONWeb令牌是一种开放的、行业标准的RFC7519方法,用于在双方之间安全地表示声明

JWT 应用场景:

Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用,JWT 省去了服务器存储用户信息的过程。

Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

 

JWT的令牌结构 看官方文档https://jwt.io/introduction/ 并解释

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:Header,Payload,Signature。

官网对于这个三部分的定义。一个典型的JWT Token是 tttttttt.yyyyyyyyyyy.eeeeeee 这样组成。

Header : 由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。然后,用Base64对这个JSON编码就得到JWT的第一部分。

 

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。分为三种类型

1:registered claims。标准声明。一般常用于校验的有 iatexpnbf 校验 token 是否过期。

      /*
        iss: jwt签发者
        sub: jwt所面向的用户
        aud: 接收jwt的一方
        exp: jwt的过期时间,这个过期时间必须要大于签发时间
        nbf: 定义在什么时间之前,该jwt都是不可用的.
        iat: jwt的签发时间
        jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
      */

2:public claims。公开声明。 可以存放任意信息,比如userid等。不是信息安全的。

3:private claims。私密声明。 双方约定的信息。

Signature Base64(header).Base64(payload) + head中定义的算法 + 密钥 生成一个字符串 。

 

使用方式:

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

// Authorization: Bearer <token>

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

 

方案是用来解决问题的,上面的这些方案没有好不好的说法,只有合不合适的说法,合适的才是最好的。

 

代码实现:  链接: https://pan.baidu.com/s/1-1vY7KgIooQ8cOVS67UOWQ 提取码: wrqh 

采用dubbo+zookeeper实现。 分为用户服务 和 sso调用两个项目。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值