广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >如何使用JWT实现单点登录
  • 489
分享到

如何使用JWT实现单点登录

2024-04-02 19:04:59 489人浏览 安东尼
摘要

本篇内容介绍了“如何使用Jwt实现单点登录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、故事起源说起

本篇内容介绍了“如何使用Jwt实现单点登录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、故事起源

说起 JWT,我们先来谈一谈基于传统session认证的方案以及瓶颈。

传统session交互流程,如下图:

如何使用JWT实现单点登录

当浏览器向服务器发送登录请求时,验证通过之后,会将用户信息存入seesion中,然后服务器会生成一个sessionId放入cookie中,随后返回给浏览器。

当浏览器再次发送请求时,会在请求头部的cookie中放入sessionId,将请求数据一并发送给服务器。

如何使用JWT实现单点登录

服务器就可以再次从seesion获取用户信息,整个流程完毕!

通常在服务端会设置seesion的时长,例如 30 分钟没有活动,会将已经存放的用户信息从seesion中移除。

session.setMaxInactiveInterval(30 * 60);//30分钟没活动,自动移除

同时,在服务端也可以通过seesion来判断当前用户是否已经登录,如果为空表示没有登录,直接跳转到登录页面;如果不为空,可以从session中获取用户信息即可进行后续操作。

如何使用JWT实现单点登录

在单体应用中,这样的交互方式,是没啥问题的。

但是,假如应用服务器的请求量变得很大,而单台服务器能支撑的请求量是有限的,这个时候就容易出现请求变慢或者OOM。

解决的办法,要么给单台服务器增加配置,要么增加新的服务器,通过负载均衡来满足业务的需求。

如果是给单台服务器增加配置,请求量继续变大,依然无法支撑业务处理。

显而易见,增加新的服务器,可以实现无限的水平扩展。

但是增加新的服务器之后,不同的服务器之间的sessionId是不一样的,可能在A服务器上已经登录成功了,能从服务器的session中获取用户信息,但是在B服务器上却查不到session信息,此时肯定无比的尴尬,只好退出来继续登录,结果A服务器中的session因为超时失效,登录之后又被强制退出来要求重新登录,想想都挺尴尬~~

面对这种情况,几位大佬于是合起来商议,想出了一个token方案。

如何使用JWT实现单点登录

将各个应用程序与内存数据库Redis相连,对登录成功的用户信息进行一定的算法加密,生成的ID被称为token,将token还有用户的信息存入redis;等用户再次发起请求的时候,将token还有请求数据一并发送给服务器,服务端验证token是否存在redis中,如果存在,表示验证通过,如果不存在,告诉浏览器跳转到登录页面,流程结束。

token方案保证了服务的无状态,所有的信息都是存在分布式缓存中。基于分布式存储,这样可以水平扩展来支持高并发

当然,现在SpringBoot还提供了session共享方案,类似token方案将session存入到redis中,在集群环境下实现一次登录之后,每个服务器都可以获取到用户信息。

二、JWT是什么

上文中,我们谈到的session还有token的方案,在集群环境下,他们都是靠第三方缓存数据库redis来实现数据的共享。

那有没有一种方案,不用缓存数据库redis来实现用户信息的共享,以达到一次登录,处处可见的效果呢?

答案肯定是有的,就是我们今天要介绍的JWT!

JWT全称JSON WEB  Token,实现过程简单的说就是用户登录成功之后,将用户的信息进行加密,然后生成一个token返回给客户端,与传统的session交互没太大区别。

交互流程如下:

如何使用JWT实现单点登录

唯一的不同点就是:token存放了用户的基本信息,更直观一点就是将原本放入redis中的用户数据,放入到token中去了!

这样一来,客户端、服务端都可以从token中获取用户的基本信息,既然客户端可以获取,肯定是不能存放敏感信息的,因为浏览器可以直接从token获取用户信息。

JWT具体长什么样呢?

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了JWT字符串。就像这样:

eyJhbGCiOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95ORM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
  • 第一部分:我们称它为头部(header),用于存放token类型和加密协议,一般都是固定的;

  • 第二部分:我们称其为载荷(payload),用户数据就存放在里面;

  • 第三部分:是签证(signature),主要用于服务端的验证;

1、header

JWT的头部承载两部分信息:

  • 声明类型,这里是JWT;

  • 声明加密的算法,通常直接使用 HMac SHA256;

完整的头部就像下面这样的jsON:

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

使用base64加密,构成了第一部分。

eyJ0eXaiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

2、playload

载荷就是存放有效信息的地方,这些有效信息包含三个部分:

  • 标准中注册的声明;

  • 公共的声明;

  • 私有的声明;

其中,标准中注册的声明 (建议但不强制使用)包括如下几个部分 :

  • iss: jwt签发者;

  • sub: jwt所面向的用户;

  • aud: 接收jwt的一方;

  • exp: jwt的过期时间,这个过期时间必须要大于签发时间;

  • nbf: 定义在什么时间之前,该jwt都是不可用的;

  • iat: jwt的签发时间;

  • jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击;

公共的声明部分:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密。

私有的声明部分:私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

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

然后将其进行base64加密,得到Jwt的第二部分:

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

3、signature

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的);

  • payload (base64后的);

  • secret (密钥);

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

//javascript var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);  var signature = HMACSHA256(encodedString, '密钥');

加密之后,得到signature签名信息。

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,就构成了最终的jwt:

//jwt最终格式 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

这个只是通过javascript实现的一个演示,JWT的签发和密钥的保存都是在服务端来完成。

secret用来进行jwt的签发和jwt的验证,所以,在任何场景都不应该流露出去。

三、实战

介绍了这么多,怎么实现呢?废话不多说,下面我们直接开撸!

<!-- jwt支持 --> <dependency>     <groupId>com.auth0</groupId>     <artifactId>java-jwt</artifactId>     <version>3.4.0</version> </dependency>
  • 然后,创建一个用户信息类,将会通过加密存放在token中

@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class UserToken implements Serializable {      private static final long serialVersionUID = 1L;           private String userId;           private String userNo;           private String userName; }
  • 接着,创建一个JwtTokenUtil工具类,用于创建token、验证token

public class JwtTokenUtil {      //定义token返回头部     public static final String AUTH_HEADER_KEY = "Authorization";      //token前缀     public static final String TOKEN_PREFIX = "Bearer ";      //签名密钥     public static final String KEY = "q3t6w9z$C&F)J@NcQfTjWnZr4u7x";          //有效期默认为 2hour     public static final Long EXPIRATION_TIME = 1000L*60*60*2;            public static String createToken(String content){         return TOKEN_PREFIX + JWT.create()                 .withSubject(content)                 .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))                 .sign(AlGorithm.HMAC512(KEY));     }           public static String verifyToken(String token) throws Exception {         try {             return JWT.require(Algorithm.HMAC512(KEY))                     .build()                     .verify(token.replace(TOKEN_PREFIX, ""))                     .getSubject();         } catch (TokenExpiredException e){             throw new Exception("token已失效,请重新登录",e);         } catch (JWTVerificationException e) {             throw new Exception("token验证失败!",e);         }     } }
  • 编写配置类,允许跨域,并且创建一个权限拦截器

@Slf4j @Configuration public class GlobalWebmvcConfig implements WebMvcConfigurer {             @Override     public void addCorsMappings(CorsReGIStry registry) {         // 添加映射路径         registry.addMapping("     @Override     public void addInterceptors(InterceptorRegistry registry) {         //添加权限拦截器         registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns(" @JwtIgnore @RequestMapping(value = "/login", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) public UserVo login(@RequestBody UserDto userDto, httpservletResponse response){     //...参数合法性验证      //从数据库获取用户信息     User dbUser = userService.selectByUserNo(userDto.getUserNo);      //....用户、密码验证      //创建token,并将token放在响应头     UserToken userToken = new UserToken();     BeanUtils.copyProperties(dbUser,userToken);      String token = JwtTokenUtil.createToken(JSONObject.toJSONString(userToken));     response.setHeader(JwtTokenUtil.AUTH_HEADER_KEY, token);       //定义返回结果     UserVo result = new UserVo();     BeanUtils.copyProperties(dbUser,result);     return result; }

到这里基本就完成了!

其中AuthenticationInterceptor中用到的JwtIgnore是一个注解,用于不需要验证token的方法上,例如验证码的获取等等。

@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface JwtIgnore {      boolean value() default true; }

而WebContextUtil是一个线程缓存工具类,其他接口通过这个方法即可从token中获取用户信息。

public class WebContextUtil {      //本地线程缓存token     private static ThreadLocal<String> local = new ThreadLocal<>();           public static void setUserToken(String content){         removeUserToken();         local.set(content);     }           public static UserToken getUserToken(){         if(local.get() != null){             UserToken userToken = JSONObject.parseObject(local.get() , UserToken.class);             return userToken;         }         return null;     }           public static void removeUserToken(){         if(local.get() != null){             local.remove();         }     } }

最后,启动项目,我们来用postman测试一下,看看头部返回结果。

如何使用JWT实现单点登录

我们把返回的信息提取处理,使用浏览器的base64对前两个部分进行解密。

  • 第一部分,也就是header,结果如下:

  • 如何使用JWT实现单点登录

  • 第二部分,也就是playload,结果如下:

  • 如何使用JWT实现单点登录

可以很清晰的看到,头部、载荷的信息都可以通过base64解密出来。

所以,一定别在token中存放敏感信息!

当我们需要请求其它服务接口时,只需要在请求头部headers中加入Authorization参数即可。

如何使用JWT实现单点登录

当权限拦截器验证通过之后,在接口方法中只需要通过WebContextUtil工具类就可以获取用户信息。

//获取用户token信息 UserToken userToken = WebContextUtil.getUserToken();

“如何使用JWT实现单点登录”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 如何使用JWT实现单点登录

本文链接: https://www.lsjlt.com/news/84988.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何使用JWT实现单点登录
    本篇内容介绍了“如何使用JWT实现单点登录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、故事起源说起 ...
    99+
    2022-10-19
  • SpringSecurityOAtu2+JWT实现微服务版本的单点登录的示例
    目录何为单点登录认证中心maven配置用户登录逻辑OAtuh2配置配置服务中心配置规则中心请求模块真实请求一些小问题何为单点登录 单点登录通俗的话来讲在微服务当中,在一个服务登录后就...
    99+
    2022-11-13
  • 单点登录的方式和JWT使用的方法是什么
    这篇文章主要介绍“单点登录的方式和JWT使用的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“单点登录的方式和JWT使用的方法是什么”文章能帮助大家解决问题。单点登录三种方式单点登录的三种实...
    99+
    2023-07-05
  • 单点登录的三种方式和JWT的介绍与使用
    单点登录三种方式 单点登录的三种实现方式: 分别为session广播机制;cookie+redis;token session广播机制指在一个集群中的一个模块登录后,然后把该sess...
    99+
    2023-03-24
    单点登录 JWT介绍 JWT使用
  • gtoken如何替换jwt实现sso登录
    今天小编给大家分享一下gtoken如何替换jwt实现sso登录的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。gtoken服务...
    99+
    2023-07-02
  • gtoken替换jwt如何实现sso登录
    这篇“gtoken替换jwt如何实现sso登录”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“gtoken替换jwt如何实现s...
    99+
    2023-06-30
  • Java SpringSecurity+JWT如何实现登录认证
    这篇文章主要介绍了Java SpringSecurity+JWT如何实现登录认证的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java SpringSecurity+JWT如何实现登录认证文...
    99+
    2023-07-02
  • 基于Node如何实现单点登录
    本文小编为大家详细介绍“基于Node如何实现单点登录”,内容详细,步骤清晰,细节处理妥当,希望这篇“基于Node如何实现单点登录”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。什么是单点登录随着公司业务的增多,必然...
    99+
    2023-07-04
  • nodejs如何实现单点登录系统
    这篇文章主要讲解了“nodejs如何实现单点登录系统”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs如何实现单点登录系统”吧!单点登录SSO(Single Sign On),就是把...
    99+
    2023-07-05
  • node如何实现单点登录系统
    今天小编给大家分享一下node如何实现单点登录系统的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一. 基础知识1.1 同源策...
    99+
    2023-07-04
  • springbootoauth2实现单点登录实例
        我们见过的很多网站,容许使用第三方账号登录,他不需要关注用户信息,只需要用户拿到授权码就可以访问。     oauth2是用...
    99+
    2022-11-12
  • PHP如何实现JWT的Token登录认证
    本篇内容介绍了“PHP如何实现JWT的Token登录认证”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、JWT简介JSON Web Tok...
    99+
    2023-06-21
  • SpringMVC拦截器如何实现单点登录
    这篇文章将为大家详细讲解有关SpringMVC拦截器如何实现单点登录,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。单点登录的功能在实际的应用场景中还是很重要的,逻辑上我们也不允许一个用户同时在进行着两个操...
    99+
    2023-05-30
  • SpringBoot如何实现同域SSO(单点登录)
    目录如何实现同域SSO?代码实现依赖配置控制器拦截器实现界面单点登录,其实看起来不是很复杂,只是细节上的处理,单点区分有三种 同域SSO 同父域SSO ...
    99+
    2022-11-12
  • SpringSecurityOAuth2单点登录和登出的实现
    目录1. 单点登录1.1 使用内存保存客户端和用户信息1.2 使用数据库保存客户端和用户信息1.3 单点登录流程1.3 JWT Token2. 单点登出3. 总结参考:Spring ...
    99+
    2022-11-13
  • 若依ruoyi实现单点登录
    系统说明(两个系统数据库用户信息username是同步的,都是唯一的) 第三方平台 若依系统(ruoyi分离版) 登录需求: 我登录到第三方平台,第三方平台嵌入我们的若依,所以在跳若依的管理页面时不想再登录了。但是验证是需要把第三方平台的t...
    99+
    2023-10-02
    java 用户登录
  • java单点登录(SSO)的实现
    单点登录(SSO):SSO是指在多个应用系统中个,用户只需要登陆一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一用户的登陆的机制。 SSO的实...
    99+
    2022-11-12
  • NodeJS怎么实现单点登录
    这篇文章主要讲解了“NodeJS怎么实现单点登录”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“NodeJS怎么实现单点登录”吧!什么是单点登录随着公司业务的增多,必然会产生各个不同的系统,如...
    99+
    2023-06-30
  • laravel单点登录怎么实现
    这篇“laravel单点登录怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“laravel单点登录怎么实现”文章吧。单...
    99+
    2023-07-02
  • SpringBoot单点登录怎么实现
    这篇文章主要介绍了SpringBoot单点登录怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot单点登录怎么实现文章都会有所收获,下面我们一起来看看吧。1.具体实现步骤添加拦截器,设置U...
    99+
    2023-07-04
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作