JWT——jjwt使用

本文介绍了JWT(JSON Web Token),它是用于身份验证和授权的安全传输数据开放标准。阐述了JWT由头部、载荷、签名构成,说明了其使用场景,如Web API验证、单点登录等。还讲解了在Java项目中使用JWT的方法,包括添加Maven依赖、生成和解析Token。

一、JWT是什么?

JWT (JSON Web Token) 是一种用于身份验证和授权的安全传输数据的开放标准。

二、JWT构成

0、header.payload.signature

1、header 头部 (JSON数据,Base64加密)

报头通常由两部分组成: Token的类型(即 JWT)和所使用的签名算法(如 HMAC SHA256或 RSA)。

  • alg : HS256 : 签名使用的算法
  • typ : JWT :标识JWT

2、payload 载荷 (JSON数据,Base64加密)

载荷是实际的数据,其中包含声明。声明是关于实体(通常是用户)和其他数据的语句。
有三种类型的声明:

  • registered claims,
  • public claims
  • private claims。

下面是预定义的数据。

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

2.1、Public claims(公共的声明)

使用 JWT 的人可以随意定义这些声明( 可以自己声明一些有效信息如用户的id,name等,但是不要设置一些敏感信息,如密码 )。但是为了避免冲突,应该在 JWT注册表中定义它们,或者将它们定义为包含抗冲突名称空间的 URI。

2.2、Private claims(私人声明)

这些是创建用于在同意使用它们的各方之间共享信息的习惯声明,既不是注册声明,也不是公开声明( 私人声明是提供者和消费者所共同定义的声明 )。

2.3 注意:

对于已签名的Token,这些信息虽然受到保护,不会被篡改,但任何人都可以阅读。除非加密,否则不要将机密信息放在 JWT 的有效负载或头元素中。

3、signature 签名:

签名用于验证JWT的完整性,确保在传输过程中没有被篡改。
公式:
HMACSHA256(base64UrlEncode(header) + “.” +base64UrlEncode(payload), secret)

三、使用场景

  • Web API:JWT可以作为一种安全且高效的方式来验证请求,保护Web API不被恶意请求和数据盗用。

  • 单点登录(SSO):JWT可以使用户在一次身份验证后,通过使用同一个认证令牌,来访问多个应用程序。这样可以简化用户在不同应用程序之间的登录流程,提高用户体验。

四、JAVA项目使用

1、Maven依赖

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.12.3</version>
</dependency>

2、生成Token方法

//私钥,注意私钥长度至少43位,不然生成Token会报错
public static String secret ="123456789a123456789a123456789a123456789a123";
public static String createToken(){
    

    // Header
    Map<String, Object> header = new HashMap<>();
    header.put("alg", "HS256");
    header.put("typ", "JWT");

    // Payload
    Map<String, Object> payload = new HashMap<>();
    payload.put("id", "malu_code");
    payload.put("name","码鹿");
    payload.put("admin",true);

    // 声明Token失效时间
    Calendar instance = Calendar.getInstance();
    instance.add(Calendar.SECOND,300);// 300s

    // 生成Token
    String token = Jwts.builder()
            .setHeader(header)// 设置Header
            .setClaims(payload) // 设置Payload
            .setExpiration(instance.getTime())// 设置生效时间
            .signWith(SignatureAlgorithm.HS256,secret) // 签名,这里采用私钥进行签名,不要泄露了自己的私钥信息
            .compact(); //生成Token

    return  token;
}

3、解析Token方法

如果可以成功解析、不报异常,那token就是对的。

//私钥,注意私钥长度至少43位,不然生成Token会报错
public static String secret ="123456789a123456789a123456789a123456789a123";
public static boolean parserToken(String token) {
    JwtParser jwtParser = Jwts.parser().setSigningKey(secret).build();
    try {
        Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
        // 解析head信息
        JwsHeader header = claimsJws.getHeader();
        // 解析Payload
        Claims claims = claimsJws.getBody();
        System.out.println(claims);
        // 解析Signature
        String signature = claimsJws.getSignature();
        System.out.println(signature); 
    }catch (Exception e){
        return false;
    }
    return true;
}
### 如何在Spring Boot项目中使用JWT进行身份验证和授权 #### 配置依赖项 为了实现基于JWT的身份验证,在`pom.xml`文件中加入必要的依赖。这通常包括用于处理JSON Web Token的库以及增强安全性框架的支持。 ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>${jjwt.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 其他所需依赖 --> ``` 这些依赖允许应用程序轻松地生成、解析和验证JWT令牌,同时也集成了强大的安全特性[^2]。 #### 创建Token工具类 定义一个辅助类来负责创建和解码JWT令牌。此类应包含方法以构建带有有效载荷声明的新令牌字符串,并能够从现有令牌提取信息。 ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; public class JwtUtil { private String secret = "yourSecretKey"; // 应该通过更安全的方式管理此密钥 public String generateToken(UserDetails userDetails){ Map<String, Object> claims = new HashMap<>(); return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .signWith(SignatureAlgorithm.HS512, secret).compact(); } public Boolean validateToken(String token, UserDetails userDetails){ final String username = getUsernameFromToken(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } private Claims extractAllClaims(String token) { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); } } ``` 注意这里提到的安全提示:不推荐直接硬编码秘密密钥;而是应当采用专业的密钥管理系统来进行管理和分发[^3]。 #### 设置认证过滤器 为了让每次HTTP请求都能自动携带并检查用户的凭证状态,需编写自定义过滤器继承`OncePerRequestFilter`,并在其中执行实际的身份验证逻辑——即读取Authorization头部字段内的Bearer类型的JWT令牌,对其进行有效性检验并将结果绑定到当前线程关联的安全上下文中去。 ```java @Component public class JwtRequestFilter extends OncePerRequestFilter { @Autowired private JwtUtil jwtUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); try{ username = jwtUtil.extractUsername(jwt); }catch(Exception e){ logger.error(e.getMessage()); } } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (Boolean.TRUE.equals(jwtUtil.validateToken(jwt, userDetails))) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } } ``` 上述代码片段展示了如何捕获传入的HTTP请求,从中抽取JWT令牌并对之实施初步审核的过程[^5]。 #### 注册过滤器至Security配置 最后一步是在全局范围内激活我们刚刚编写的过滤器实例,使之成为整个Web应用防护链的一部分。为此可以在扩展了`WebSecurityConfigurerAdapter`的基础之上重写其内部的方法: ```java @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtRequestFilter jwtRequestFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(). authorizeRequests().antMatchers("/authenticate").permitAll(). anyRequest().authenticated(). and(). sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS). and(). addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 这段配置指定了哪些路径无需经过身份验证即可访问(如登录页面),其余资源则一律受保护。同时禁用了CSRF防御机制因为无状态API不需要它,并指定每当收到新请求时都要先调用前面定义好的JwtRequestFilter对象做前置处理工作[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码鹿的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值