Spring Boot项目中集成JWT进行身份验证

什么是JWT?

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境中安全地传递信息。它主要用于在客户端和服务器之间传递经过签名的 JSON 数据,以确保数据的完整性和真实性。

1.JWT 的结构

一个标准的 JWT 包含三个部分:
(1) 头部(Header):通常包括令牌的类型(如 "JWT")以及所使用的签名算法(如 HMAC SHA256 或 RSA)。

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

(2) 有效负载(Payload):包含声明(Claims),这些声明可以是关于用户的身份、权限或其他信息的内容。有效负载部分可以包含三种类型的声明:
注册声明(Registered Claims):预定义的声明,例如  sub (主题)、 exp (过期时间)等。
公共声明(Public Claims):可以自定义声明,但为了避免冲突,建议在 IANA 注册表中注册。
私有声明(Private Claims):自定义的声明,通常用于特定的应用程序或服务。

{
     "sub": "1234567890",
     "name": "John Doe",
     "iat": 1516239022
}

(3)签名(Signature):为了生成签名,必须有头部和有效负载的编码,并且使用指定的算法和密钥进行签名。例如,如果使用 HMAC SHA256 算法,则签名的生成方式如下:

 HMACSHA256(
     base64UrlEncode(header) + "." +
     base64UrlEncode(payload),
     your-256-bit-secret
   )

2.JWT 的用途

身份验证(Authentication):JWT 通常用于用户登录后的身份验证。用户登录时,服务器生成一个 JWT,并将其返回给客户端,客户端在后续请求中携带这个 JWT,以证明其身份。
信息交换(Information Exchange):JWT 也可以用于在不同系统之间安全地传递信息,因为签名可以验证消息的完整性和真实性。

3.JWT 的优点

紧凑性:JWT 可以通过 URL、POST 参数或在 HTTP 头部中传输,适合在 HTTP 中传输。
自包含:JWT 包含了所有用户验证所需的信息,无需查询数据库即可验证信息。

4.JWT 的缺点

安全性问题:如果密钥泄露,JWT 的安全性将受到威胁。由于 JWT 自包含所有信息,攻击者可能会利用这些信息进行攻击。
不可撤销:一旦 JWT 被发放,即使用户退出登录或权限更改,也不会立即撤销,直到 JWT 过期或失效。

在Spring Boot项目中集成JWT进行身份验证

在 Spring Boot 项目中集成 JWT 进行身份验证通常涉及以下几个步骤:

1. 添加依赖

首先,确保你的  pom.xml  文件中包含所需的依赖。如果你使用的是 Maven,添加以下依赖项:   

 <dependencies>
       <!-- Spring Boot Starter Web -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <!-- Spring Boot Starter Security -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-security</artifactId>
       </dependency>

       <!-- JWT Library -->
       <dependency>
           <groupId>io.jsonwebtoken</groupId>
           <artifactId>jjwt</artifactId>
           <version>0.9.1</version>
       </dependency>
   </dependencies>

2. 创建 JWT 工具类

编写一个工具类用于生成和解析 JWT。这个类将负责创建 JWT 并验证其有效性。  

 import io.jsonwebtoken.Claims;
   import io.jsonwebtoken.Jwts;
   import io.jsonwebtoken.SignatureAlgorithm;
   import org.springframework.beans.factory.annotation.Value;
   import org.springframework.stereotype.Component;

   import java.util.Date;

   @Component
   public class JwtUtil {

       @Value("${jwt.secret}")
       private String secretKey;

       @Value("${jwt.expiration}")
       private long expiration;

       public String generateToken(String username) {
           return Jwts.builder()
                   .setSubject(username)
                   .setIssuedAt(new Date())
                   .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                   .signWith(SignatureAlgorithm.HS256, secretKey)
                   .compact();
       }

       public Claims extractClaims(String token) {
           return Jwts.parser()
                   .setSigningKey(secretKey)
                   .parseClaimsJws(token)
                   .getBody();
       }

       public String extractUsername(String token) {
           return extractClaims(token).getSubject();
       }

       public boolean isTokenExpired(String token) {
           return extractClaims(token).getExpiration().before(new Date());
       }

       public boolean validateToken(String token, String username) {
           return (username.equals(extractUsername(token)) && !isTokenExpired(token));
       }
   }

3. 配置 Spring Security

创建一个自定义的 JwtAuthenticationFilter  来处理 JWT 的验证和解析。  

 import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
   import org.springframework.security.core.context.SecurityContextHolder;
   import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

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

   public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

       @Autowired
       private JwtUtil jwtUtil;

       @Override
       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
               throws IOException, ServletException {
           HttpServletRequest httpServletRequest = (HttpServletRequest) request;
           String authHeader = httpServletRequest.getHeader("Authorization");

           if (authHeader != null && authHeader.startsWith("Bearer ")) {
               String token = authHeader.substring(7);
               String username = jwtUtil.extractUsername(token);

               if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                   if (jwtUtil.validateToken(token, username)) {
                       UsernamePasswordAuthenticationToken authentication =
                               new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
                       SecurityContextHolder.getContext().setAuthentication(authentication);
                   }
               }
           }

           chain.doFilter(request, response);
       }
   }

4. 配置 Spring Security 以使用 JWT 过滤器

 import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.context.annotation.Bean;
   import org.springframework.context.annotation.Configuration;
   import org.springframework.security.config.annotation.web.builders.HttpSecurity;
   import org.springframework.security.config.annotation.web.builders.WebSecurity;
   import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
   import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

   @Configuration
   @EnableWebSecurity
   public class SecurityConfig extends WebSecurityConfigurerAdapter {

       @Autowired
       private JwtAuthenticationFilter jwtAuthenticationFilter;

       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http.csrf().disable()
               .authorizeRequests()
               .antMatchers("/public/**").permitAll()
               .anyRequest().authenticated()
               .and()
               .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
       }
   }

5. 配置 application.properties

配置 JWT 的秘密密钥和过期时间。

   jwt.secret=mySecretKey
   jwt.expiration=86400

6. 创建控制器

创建一个控制器来处理用户登录和返回 JWT 令牌。   


   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.web.bind.annotation.PostMapping;
   import org.springframework.web.bind.annotation.RequestBody;
   import org.springframework.web.bind.annotation.RestController;

   @RestController
   public class AuthController {

       @Autowired
       private JwtUtil jwtUtil;

       @PostMapping("/login")
       public String login(@RequestBody LoginRequest loginRequest) {
           // 验证用户凭证(用户名和密码)
           // 省略实际验证逻辑

           return jwtUtil.generateToken(loginRequest.getUsername());
       }
   }

其中  LoginRequest  是一个包含  username 和  password  的请求体类。


。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值