JWT与传统Token机制对比:实现安全高效的用户认证

打印 上一主题 下一主题

主题 865|帖子 865|积分 2595

        在现代Web应用步伐中,用户认证是一个至关重要的环节。传统的Session机制固然简单易用,但在分布式体系中却面对诸多挑战。相比之下,JSON Web Tokens(JWT)作为一种轻量级的认证机制,因其无需依靠服务器端存储用户状态的特点而受到广泛青睐。本文将深入探究JWT的工作原理、优缺点以及在实际项目中的整合策略。
一、JWT简介


        JWT是一种开放尺度(RFC 7519),它界说了一种自包罗的凭据,用于在各方之间以安全的方式传输信息。JWT由三部分组成:Header(头部)、Payload(载荷)和Signature(签名)。


  • Header:包罗了令牌范例和签名算法的信息。比方:
    1. {
    2.     "alg":"HS256",
    3.     "type","JWT"
    4. }
    复制代码
  • Payload:是JWT的主题部分,包罗了一系列声明(Claims)。声明是关于主体的信息,通常用来传输用户数据。比方:
    1. 1{
    2. 2  "userId": "1",
    3. 3  "username": "mayikt"
    4. 4}
    复制代码
  • Signature:用于验证数据的完备性和确认JWT是否被篡改。它是通过将Header、Payload和一个密钥(Secret)按照指定算法盘算得出的结果。这个密钥只能由服务端持有,并且用于验证JWT的有效性。
        其中,尺度中注册的声明有


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


2.1 Session机制的范围性


        在传统的Web应用中,Session是最常用的用户状态管理方案。然而,随着微服务架构的兴起,Session机制面对着如下挑战:


  • 集群环境下共享困难:在分布式体系中,由于Session数据通常存储在单台服务器上,导致其他节点无法访问到同一用户的Session信息,这限定了体系的横向扩展能力。
2.2 传统Token机制


        传统的Token机制通常指通过用户登录生成一个唯一的标识符(Token),并将此Token与用户ID关联后存储在Redis等缓存数据库中。客户端每次请求时都必要携带这个Token,服务器则通过查询Redis来验证Token的有效性。
        这种方式固然解决了Session在分布式环境下的共享问题,但仍存在以下不敷:


  • 埋伏了数据的真实性:由于Token本身并不包罗任何用户信息,因此服务器必须每次都查询数据库来获取用户详情。
2.3 JWT的优势


与上述两种方案相比,JWT具有以下显着优点:

  • 减轻服务器端压力:JWT将用户信息直接编码在Token内,无需每次请求都查询数据库。
  • 轻量级且易于解析:采用JSON格式,便于前后端之间的数据互换。
  • 跨语言支持:由于其基于尺度的开放协议,可以在不同编程语言之间无缝集成。

三、JWT在项目中的应用


3.1 Maven依靠设置


        要在Spring Boot项目中利用JWT,直接引入干系依靠即可:
  1.      <!--   jwt 依赖     -->
  2.         <dependency>
  3.             <groupId>io.jsonwebtoken</groupId>
  4.             <artifactId>jjwt</artifactId>
  5.             <version>0.9.1</version>
  6.         </dependency>
复制代码
        之后即可通过生成或解析token,示比方下:
  1. //存入用户信息,生成token
  2. // jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
  3. JwtBuilder jwtBuilder = Jwts.builder()
  4.     .setId("8888")
  5.     .setSubject("Rose")      // jwt所面向的用户
  6.     .setIssuedAt(new Date())  //创建token的日期
  7.     .signWith(SignatureAlgorithm.HS256,"abcde") //使用的算法,加密的盐值,盐值不能太短,否则报错
  8.     .setExpiration(new Date(System.currentTimeMillis()+过期时间毫秒))  //设置token失效时间
  9.             //可以通过claim方法自定义添加属性到token里面,使用key-value格式,
  10.              // 也可以直接传入map,通过addClaims(map)实现
  11.     .claim("name","admin")
  12.     .claim("logo","xxx.jpg");
复制代码
  1. //使用jwts解析token
  2. Claims body = Jwts.parser().setSigningKey("abcde") //预先设置的盐值
  3.                                     .parseClaimsJws(token)//要解析的token,jws即签名后的jwt
  4.                                     .getBody();    //获取信息
  5. //通过body获取内部信息
  6. String name = body.get("name");
复制代码
3.2 整合Spring Security


        为了更好地保护API接口,通常还会结合Spring Security框架来实现基于JWT的安全认证。此时,必要添加额外的依靠:
  1.         <!--添加security提供的jwt包,使用security整合oauth2.0-->
  2.         <dependency>
  3.             <groupId>org.springframework.security</groupId>
  4.             <artifactId>spring-security-jwt</artifactId>
  5.             <version>1.1.1.RELEASE</version>
  6.         </dependency>
复制代码
3.2.1 设置Token存储策略

        设置token存储策略,设置JwtTokenStoreConfig类,利用jwt存储token
  1. /**
  2. * jwt配置类,
  3. * 1,设置token存储方式为jwt存储,并将TokenStore注入的spring容器
  4. *
  5. *,2,配置jwt生成token的返回实现类,JwtAccessTokenConverter,设置秘钥,返回JwtAccessTokenConverter对象,注入容器
  6. */
  7. @Configuration
  8. public class JwtTokenStoreConfig{
  9.     /**
  10.      *  设置token存储方式为jwt存储
  11.      * @return
  12.      */
  13.     @Bean
  14.     public TokenStore jwtTokenStore(){
  15.         return new JwtTokenStore(jwtAccessTokenConverter());
  16.     }
  17.     //配置jwt生成token的返回实现类
  18.     @Bean
  19.     public JwtAccessTokenConverter jwtAccessTokenConverter(){
  20.         JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  21.         //配置jwt使用的秘钥
  22.         converter.setSigningKey("test_key");
  23.         return converter;
  24.     }
  25.     //将jwt内容增强器注入为bean
  26.     @Bean
  27.     public JwtTokenEnhancer jwtTokenEnhancer(){
  28.         return new JwtTokenEnhancer();
  29.     }
  30. }
复制代码
        其中,JwtTokenEnhancer类用于在JWT中添加自界说信息:
  1. /**
  2. * jwt内容增强器,即通过该类可以在token当中添加自定义的属性
  3. *
  4. *
  5. */
  6. public class JwtTokenEnhancer implements TokenEnhancer {
  7.     @Override
  8.     public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
  9.         Map<String, Object> info = new HashMap<>();
  10.         info.put("enhance","enhance info");
  11.         //oAuth2AccessToken向上转型为DefaultOAuth2AccessToken,获取方法setAdditionalInformation,通过该方法添加内容到token
  12.         ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(info);
  13.         return oAuth2AccessToken;
  14.     }
  15. }
复制代码
3.2.2 客户端授权设置

  1.     @Autowired
  2.     private PasswordEncoder passwordEncoder;
  3.     /**
  4.      * 预先设置TokenStore(token存储方式)为jwt存储,并注入spring容器,redis存储无需配置token转换器
  5.      * 此处需要配合@Qualifier注解使用name属性注入,因为TokenStore类型的实现类不止一个,type类型的注入无法识别应该注入哪一个bean
  6.      */
  7.     @Autowired
  8.     @Qualifier("jwtTokenStore")
  9.     private TokenStore tokenStore;
  10.     //注入accessToken和JwtToken的相互转换的处理类
  11.     @Autowired
  12.     private JwtAccessTokenConverter jwtAccessTokenConverter;
  13.     //自动注入jwt内容增强器
  14.     @Autowired
  15.     private JwtTokenEnhancer jwtTokenEnhancer;
  16.     /**
  17.      ** 密码模式需要重写该方法,并且需要提前把AuthenticationManager注入到spring容器
  18.      */
  19.      @Autowired
  20.      private UserService userService;
  21.      @Autowired
  22.      private AuthenticationManager authenticationManager;
  23.     @Override
  24.     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  25.         //配置jwt内容增强,即额外向token添加自定义属性
  26.         TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
  27.         List<TokenEnhancer> delegates = new ArrayList<>() ;
  28.         delegates.add(jwtTokenEnhancer);
  29.         delegates.add(jwtAccessTokenConverter);
  30.         tokenEnhancerChain.setTokenEnhancers(delegates);
  31.         //使用用户手动授权,即开启密码模式
  32.         endpoints.authenticationManager(authenticationManager)
  33.                 .userDetailsService(userService)
  34.                 //设置token存储方式,此处为jwt存储token
  35.                 .tokenStore(tokenStore)
  36.                 //使用jwtAccessTokenConverter生成token
  37.                 .accessTokenConverter(jwtAccessTokenConverter)
  38.                 //添加自定义token属性
  39.                 .tokenEnhancer(tokenEnhancerChain);
  40.     }
复制代码
四、末了


        JWT作为一种新兴的身份验证机制,以其独特的自包罗特性解决了传统Session机制在分布式环境下的范围性。它不但简化了开辟流程,提高了体系性能,同时也为构建更加安全可靠的Web应用提供了有力支持。然而,JWT也有其固有的缺陷,好比一旦生结果无法修改等问题。因此,在实际应用中,开辟者需根据具体场景灵活选择最符合的认证方案。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表