Springboot 开发 -- 集成 JWT 构建安全的API接口服务

一、JWT简介

JSON Web Token(JWT)是一种基于JSON的开放标准(RFC 7519),用于在各方之间以JSON对象的形式安全地传输信息。JWT可以被签名,确保信息在传输过程中的完整性和可信度。JWT通常用于身份验证和信息交换,特别适用于分布式系统和跨域认证场景。

官网地址:https://jwt.io/introduction/
中文网站:http://jwt.uihtm.com/

二、为什么使用JWT

相较于传统的Session认证,JWT具有以下优势:

  • 无状态和可扩展性:服务端不需要存储Session信息,易于扩展。
  • 跨域认证:JWT可以在不同的域之间传递,便于单点登录(SSO)的实现。
  • 安全性:JWT可以通过数字签名保证信息传输的安全性。
  • 自包含:JWT包含了所有用户验证所需的信息,减少了数据库查询。

三、JWT的结构

JWT由三部分组成,用.连接:

Header(头部信息):包含令牌的类型和所使用的签名算法。
Payload(有效载荷):包含所谓的Claims(声明),它们是关于实体(通常是用户)和其他数据的声明。
Signature(签名):用于验证消息在传输过程中未被篡改,并且,对于使用私钥签名的令牌,还可以验证发送者的身份。

因此,JWT 格式通常如下所示。

xxxxx.yyyyy.zzzzz

1. 头部信息

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

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

然后,这个 JSON 被Base64Url编码以形成 JWT 的第一部分。

2. 有效载荷

包含声明。声明是关于实体(通常是用户)和附加数据的陈述。索赔分为三种类型:注册索赔、公开索赔和私人索赔。
一个示例有效载荷可能是::

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

然后对有效负载进行Base64Url编码以形成 JSON Web 令牌的第二部分。

3. 签名

要创建签名部分,必须获取编码的标头、编码的有效负载、秘密、标头中指定的算法,并对其进行签名。

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

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

签名用于验证消息在此过程中没有被更改,并且在使用私钥签名的令牌的情况下,它还可以验证 JWT 的发送者就是它所说的那个人。

四、 验证 JWT

如果想玩 JWT 并将这些概念付诸实践,可以使用 jwt.io Debugger 来解码、验证和生成 JWT。
在这里插入图片描述

五、JWT 交互流程

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据
    在这里插入图片描述

六、SpringBoot集成JWT

1. 添加依赖

在SpringBoot项目的pom.xml中添加JWT的依赖,例如使用java-jwt库:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.2</version> <!-- 请使用最新版本 -->
</dependency>

2. 创建JWT工具类

创建一个工具类来生成和验证JWT:

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTokenUtil {
    private String secret = "secretKey"; // 密钥

    public String generateToken(String username) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + 1000 * 60 * 60); // 1小时后过期

        Map<String, Object> claims = new HashMap<>();
        claims.put("username", username);

        return JWT.create()
                .withIssuer("yourIssuer") // 发行人
                .withIssuedAt(now)
                .withExpiresAt(expiryDate)
                .withClaim("username", username)
                .sign(Algorithm.HMAC256(secret));
    }

    public String getUsername(String token) {
        DecodedJWT jwt = JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
        return jwt.getClaim("username").asString();
    }

    // 验证Token
    public boolean validateToken(String token, String username) {
        try {
            DecodedJWT jwt = JWT.require(Algorithm.HMAC256(secret))
                    .withClaim("username", username)
                    .build()
                    .verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

3. 创建认证过滤器

创建一个过滤器来拦截请求,并验证JWT的有效性:

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenUtil jwtTokenUtil;

    public JwtAuthenticationFilter(JwtTokenUtil jwtTokenUtil) {
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        final String authorizationHeader = request.getHeader("Authorization");
        String token = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            token = authorizationHeader.substring(7);
        }
        String username = null;
        boolean isTokenValid = false;
        if (token != null) {
            username = jwtTokenUtil.getUsername(token);
            isTokenValid = jwtTokenUtil.validateToken(token, username);
        }
        if (!isTokenValid) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        filterChain.doFilter(request, response);
    }
}

4. 创建用户登录接口

创建一个用户登录接口,用于生成JWT:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class AuthenticationController {

    private final JwtTokenUtil jwtTokenUtil;

    public AuthenticationController(JwtTokenUtil jwtTokenUtil) {
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @PostMapping("/login")
    public Map<String, String> login(@RequestBody LoginRequest loginRequest) {
        String username = loginRequest.getUsername();
        // 这里应该添加验证用户名和密码的逻辑
        // 如果验证成功
        String token = jwtTokenUtil.generateToken(username);
        Map<String, String> responseMap = new HashMap<>();
        responseMap.put("token", token);
        return responseMap;
    }
}

五、客户端存储和使用JWT

客户端(通常是浏览器)在收到JWT后,应将其存储在本地,如LocalStorage或SessionStorage中。在随后的请求中,客户端需要在HTTP请求头中添加JWT,以验证用户身份。

六、总结

通过上述步骤,我们成功地在SpringBoot项目中集成了JWT,实现了API接口服务的身份验证。JWT提供了一种安全、高效的方式来处理身份验证和信息交换,特别适合于微服务和分布式系统。然而,需要注意的是,JWT不适用于需要高度安全的场景,如支付系统,因为JWT一旦发出,就无法撤销,除非等到它自然过期。此外,由于JWT通常存储在客户端,因此它们容易受到跨站脚本攻击(XSS)的影响。开发者应采取适当的安全措施来保护JWT,例如使用HttpOnly的Cookie标志来存储令牌,或者使用内容安全策略(CSP)来减轻XSS攻击的风险。

  • 74
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot 集成 JWT(JSON Web Token)可以提供一种安全且可靠的身份验证和授权机制。JWT 是一种基于 JSON 的开放标准(RFC 7519),它定义了一种紧凑且自包含的方式来在网络上安全地传输信息。 要在 Spring Boot 中使用 JWT,可以使用第三方库(例如 jjwt 或者 auth0),它们提供了生成和解析 JWTAPI。你需要在你的项目中引入相应的依赖,然后在代码中使用相应的 API 来实现 JWT 的生成和验证。 通常来说,生成 JWT 需要指定一个密钥(secret),这个密钥会被用来加密和验证 JWT。在 Spring Boot 中,可以通过在配置文件中设置属性来指定密钥。 具体实现过程可以参考一些开源项目或者教程,例如 Spring 官方文档中关于使用 jjwt 实现 JWT 的示例。 ### 回答2: Spring Boot是一种开发框架,它可以帮助开发人员快速构建基于Java的应用程序。JWT(JSON Web Token)是一种安全传输身份验证信息的方法。将Spring Boot和JWT集成在一起可以实现更安全的身份验证和授权机制。 首先,我们需要在Spring Boot项目中添加所需的依赖项。可以使用Maven或Gradle来管理项目依赖。可以添加Spring Security依赖项以实现身份验证和授权功能,以及jjwt依赖项以实现JWT相关功能。 然后,我们需要配置Spring Security以支持JWT。可以创建一个继承自`WebSecurityConfigurerAdapter`的类,并覆盖`configure`方法。在该方法中,我们可以定义哪些URL需要进行身份验证,以及如何配置身份验证提供者。通常,我们会创建一个自定义的身份验证提供者,通过验证JWT中的令牌信息来验证用户身份。 接下来,我们可以定义自己的登录接口。在登录接口中,用户可以提交用户名和密码,服务器会验证用户信息,并生成一个JWT令牌。该JWT令牌会被返回给用户,并在以后的请求中用于身份验证。 在其他需要进行身份验证的接口中,我们可以通过在接口方法上添加`@PreAuthorize`注解来指定访问权限。该注解可以根据用户的角色或其他信息来控制接口的访问权限。 最后,我们需要编写相应的代码来处理JWT令牌的生成、验证和解析。可以使用jjwt库来处理JWT相关操作。可以创建一个JWTUtil类,其中包含生成JWT令牌、验证JWT令牌和解析JWT令牌的方法。 通过以上步骤,我们就可以在Spring Boot项目中成功集成JWT了。这样就能实现更安全的身份验证和授权机制,保护我们的应用程序免受未经授权的访问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值