JWT简单应用

简介

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

使用场景

授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,允许用户访问该令牌允许的路由,服务和资源。Single Sign On是一种现在广泛使用JWT的功能,因为它的开销很小,并且能够在不同的域中轻松使用。
信息交换:JSON Web令牌是在各方之间安全传输信息的好方法。因为JWT可以签名 - 例如,使用公钥/私钥对 - 您可以确定发件人是他们所说的人。此外,由于使用标头和有效负载计算签名,您还可以验证内容是否未被篡改。

组成结构

JSON Web令牌由三个部分组成(由点(.)分隔,它们是:

  • 有效载荷
  • 签名

因此,JWT通常如下所示。
xxxxx.yyyyy.zzzzz

标头通常由两部分组成:令牌的类型,即JWT,以及正在使用的散列算法,例如HMAC SHA256或RSA。

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

然后,这个JSON被编码为Base64Url,形成JWT的第一部分。
有效载荷

{
  "name": "大明",
  "_id": "123",
  "iat": 1534774285, //JWT生成时间
  "exp": 1534777885 //过期时间
}

然后,有效负载经过Base64Url编码,形成JSON Web令牌的第二部分。
签名
要创建签名部分,您必须采用编码标头,编码的有效负载,秘密,标头中指定的算法,并对其进行签名。

例如,如果要使用HMAC SHA256算法,将按以下方式创建签名:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

在koa中使用JWT

npm install jsonwebtoken --save-dev //生成JWT
npm install koa-jwt --save-dev //验证JWT

在controller中

//userController.js
const jwt = require("jsonwebtoken");
const cert = require("../../config/config").cert; //秘钥

exports.login = async (ctx, next) => {
  return (ctx.body = {
    token: jwt.sign(
      {
        name: "大明",
        _id: "123"
      },//这里的数据可以是我们登录成功返回的一些用户数据
      cert,
      { expiresIn: 60 * 60 } //时间间隔
    )
  });
};

这样用户通过登录就可以接收到服务器返回的token
客户端请求受保护的服务器资源时需要携带token否则不允许访问。

//app.js
const koajwt = require("koa-jwt");
// 错误处理
app.use((ctx, next) => {
  return next().catch(err => {
    if (err.status === 401) {
      ctx.status = 401;
      ctx.body = "Protected resource, use Authorization header to get access\n";
    } else {
      throw err;
    }
  });
});
//校验登录
app.use(
  koajwt({
    secret: cert //秘钥
  }).unless({
    path: [/\/users\/login/]
  }) //unless表示不校验token的url
);

通过 app.use 来调用该中间件,并传入密钥 {secret: ‘my_token’},unless 可以指定哪些 URL 不需要进行 token 验证。token 验证失败的时候会抛出401错误,因此需要添加错误处理,而且要放在 app.use(koajwt()) 之前,否则不执行。

客户端请求需要在header中携带如下请求头

authorization:Bearer token //token为服务器返回的token

更多详情请参考JWT官方网站

以下是一个简单的使用Spring Boot和JWT的示例: 首先,添加以下依赖项到你的pom.xml文件中: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 接下来,配置JWT的一些属性,例如密钥,过期时间等: ```java @Configuration public class JwtConfig { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private int expiration; public String getSecret() { return secret; } public void setSecret(String secret) { this.secret = secret; } public int getExpiration() { return expiration; } public void setExpiration(int expiration) { this.expiration = expiration; } } ``` 创建一个过滤器来处理JWT: ```java public class JwtTokenFilter extends OncePerRequestFilter { @Autowired private JwtConfig jwtConfig; @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { try { String jwt = parseJwt(httpServletRequest); if (jwt != null && validateJwtToken(jwt)) { Authentication authentication = getAuthentication(jwt); SecurityContextHolder.getContext().setAuthentication(authentication); } } catch (Exception e) { logger.error("Cannot set user authentication: {}", e); } filterChain.doFilter(httpServletRequest, httpServletResponse); } private String parseJwt(HttpServletRequest request) { String headerAuth = request.getHeader("Authorization"); if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { return headerAuth.substring(7, headerAuth.length()); } return null; } private boolean validateJwtToken(String jwt) { try { Jwts.parser().setSigningKey(jwtConfig.getSecret()).parseClaimsJws(jwt); return true; } catch (SignatureException e) { logger.error("Invalid JWT signature: {}", e.getMessage()); } catch (MalformedJwtException e) { logger.error("Invalid JWT token: {}", e.getMessage()); } catch (ExpiredJwtException e) { logger.error("JWT token is expired: {}", e.getMessage()); } catch (UnsupportedJwtException e) { logger.error("JWT token is unsupported: {}", e.getMessage()); } catch (IllegalArgumentException e) { logger.error("JWT claims string is empty: {}", e.getMessage()); } return false; } private Authentication getAuthentication(String jwt) { Claims claims = Jwts.parser() .setSigningKey(jwtConfig.getSecret()) .parseClaimsJws(jwt) .getBody(); String username = claims.getSubject(); List<String> roles = (List<String>) claims.get("roles"); List<GrantedAuthority> authorities = roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); return new UsernamePasswordAuthenticationToken(username, null, authorities); } } ``` 接下来,创建一个JWT生成器: ```java @Service public class JwtUtils { @Autowired private JwtConfig jwtConfig; public String generateJwtToken(Authentication authentication) { UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); return Jwts.builder() .setSubject((userPrincipal.getUsername())) .setIssuedAt(new Date()) .setExpiration(new Date((new Date()).getTime() + jwtConfig.getExpiration() * 1000)) .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret()) .compact(); } } ``` 最后,将JWT过滤器添加到Spring Security配置中: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtTokenFilter jwtTokenFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 这样,你就可以在你的Spring Boot应用中使用JWT进行身份验证了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值