测试JWT启动Spring Boot应用程序

发布时间:2025-06-24 19:13:49  作者:北方职教升学中心  阅读量:952


项目结构

  • 二、其中可以包含注册声明(如 iss、依赖配置
  • 三、测试JWT

  • JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间以紧凑的方式安全地传递信息。

    JWT的格式如下:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    2. JWT的优点

    • 无状态: 不需要在服务器存储会话信息,减轻了服务器的负担。身份验证控制器
    • 八、

      一、

      1. JWT的结构

      JWT由三部分组成:

      • Header(头部): 通常包含令牌的类型(JWT)和所使用的签名算法(如HMAC SHA256或RSA)。

      • 自包含: 含有用户身份信息,避免频繁查询数据库。

        目录

        • 1. JWT的结构
        • 2. JWT的优点
        • 3. JWT的流转过程
        • 4.具体案例
            • 一、项目结构

              Spring Boot项目结构如下:

              src├── main│   ├── java│   │   └── com│   │       └── example│   │           └── jwt│   │               ├── JwtApplication.java│   │               ├── config│   │               │   └── SecurityConfig.java│   │               ├── controller│   │               │   └── AuthController.java│   │               ├── model│   │               │   └── User.java│   │               ├── service│   │               │   └── JwtUtil.java│   │               └── filter│   │                   └── JwtRequestFilter.java│   └── resources│       └── application.properties└── test

              二、

            • 服务器解析JWT,验证其有效性,允许或拒绝请求。JWT请求过滤器

              创建JWT请求过滤器,用于拦截请求并验证JWT:

              packagecom.example.jwt.filter;importcom.example.jwt.service.JwtUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.security.core.context.SecurityContextHolder;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.core.userdetails.UserDetailsService;importorg.springframework.security.web.authentication.WebAuthenticationDetailsSource;importorg.springframework.stereotype.Component;importorg.springframework.web.filter.OncePerRequestFilter;importjavax.servlet.FilterChain;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;@Component// 将该类标记为 Spring 组件,以便自动扫描和管理publicclassJwtRequestFilterextendsOncePerRequestFilter{@Autowired// 自动注入 JwtUtil 实例privateJwtUtiljwtUtil;@Autowired// 自动注入 UserDetailsService 实例privateUserDetailsServiceuserDetailsService;@OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainchain)throwsServletException,IOException{// 从请求中获取 Authorization 头部finalStringauthorizationHeader =request.getHeader("Authorization");Stringusername =null;// 初始化用户名Stringjwt =null;// 初始化 JWT 令牌// 检查 Authorization 头部是否存在且以 "Bearer " 开头if(authorizationHeader !=null&&authorizationHeader.startsWith("Bearer ")){// 提取 JWT 令牌(去掉 "Bearer " 前缀)jwt =authorizationHeader.substring(7);// 从 JWT 中提取用户名username =jwtUtil.extractUsername(jwt);}// 如果用户名不为空且当前 SecurityContext 没有身份验证信息if(username !=null&&SecurityContextHolder.getContext().getAuthentication()==null){// 根据用户名加载用户详细信息UserDetailsuserDetails =userDetailsService.loadUserByUsername(username);// 验证 JWT 是否有效if(jwtUtil.validateToken(jwt,userDetails.getUsername())){// 创建身份验证令牌,并设置用户的权限UsernamePasswordAuthenticationTokenauthenticationToken =newUsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());// 设置请求的详细信息authenticationToken.setDetails(newWebAuthenticationDetailsSource().buildDetails(request));// 将身份验证信息存入 SecurityContextSecurityContextHolder.getContext().setAuthentication(authenticationToken);}}// 继续过滤器链chain.doFilter(request,response);}}

              六、

            • 使用Postman或其他工具测试登录接口。测试JWT
              1. 启动Spring Boot应用程序。exp、JWT可以被用作身份验证和信息交换的手段,特别适合用于前后端分离的应用程序。用户模型
              2. 四、它接受用户名作为参数。

              3. Signature(签名): 用于验证消息的完整性和发送者的身份。JWT工具类

                创建JWT工具类,负责生成和解析JWT:

                packagecom.example.jwt.service;importio.jsonwebtoken.Claims;importio.jsonwebtoken.Jwts;importio.jsonwebtoken.SignatureAlgorithm;importorg.springframework.stereotype.Component;importjava.util.Date;importjava.util.HashMap;importjava.util.Map;/***Jwt工具类*/@Component//加入Spring容器publicclassJwtUtil{privateStringsecret ="your_secret_key";// 强密码privatelongexpiration =60*60*1000;// 1小时//这个方法用于生成 JWT。publicStringgenerateToken(Stringusername){Map<String,Object>claims =newHashMap<>();returncreateToken(claims,username);}//私有方法,用于实际生成 JWTprivateStringcreateToken(Map<String,Object>claims,Stringsubject){returnJwts.builder()//开始构建 JWT 的构建器.setClaims(claims)//设置 JWT 中的声明.setSubject(subject)//设置主题(通常是用户名).setIssuedAt(newDate(System.currentTimeMillis()))//设置 JWT 的签发时间.setExpiration(newDate(System.currentTimeMillis()+expiration))//设置 JWT 的过期时间.signWith(SignatureAlgorithm.HS256,secret)//使用指定的算法(HS256)和密钥对 JWT 进行签名.compact();//生成最终的 JWT 字符串}//用于验证给定的 JWT 是否有效。安全配置
              4. 七、
              5. 服务器验证用户信息,如果成功,则生成JWT并返回给用户。JWT工具类
              6. 五、

            3. JWT的流转过程

            1. 用户通过登录接口发送用户名和密码。
            2. 用户在后续请求中带上JWT,通常放在HTTP请求的Authorization头中。依赖配置

              pom.xml中添加必要的依赖:

              <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency></dependencies>

              三、

            3. Payload(负载): 包含声明(claims),即要传递的数据。publicBooleanvalidateToken(Stringtoken,Stringusername){finalStringextractedUsername =extractUsername(token);//提取 JWT 中的用户名return(extractedUsername.equals(username)&&!isTokenExpired(token));//检查提取的用户名与提供的用户名是否匹配,并且检查 JWT 是否未过期}//从 JWT 中提取用户名publicStringextractUsername(Stringtoken){returnextractAllClaims(token).getSubject();}//解析 JWT 并返回所有声明privateClaimsextractAllClaims(Stringtoken){returnJwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}//使用密钥解析 JWT 获取其主体部分(声明)//检查 JWT 是否已过期privateBooleanisTokenExpired(Stringtoken){returnextractAllClaims(token).getExpiration().before(newDate());}}

              五、

            4.具体案例

            好的,让我们更详细地探讨如何在Java Spring Boot应用程序中实现JWT身份验证,包括每一步的代码和说明。用户模型

            创建一个简单的用户模型:

            packagecom.example.jwt.model;publicclassUser{privateStringusername;privateStringpassword;// Constructors, getters, and setters//也可以使用LombokpublicUser(Stringusername,Stringpassword){this.username =username;this.password =password;}publicStringgetUsername(){returnusername;}publicStringgetPassword(){returnpassword;}}

            四、身份验证控制器

            创建一个控制器来处理登录请求并返回JWT:

            packagecom.example.jwt.controller;importcom.example.jwt.model.User;importcom.example.jwt.service.JwtUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.core.userdetails.UserDetailsService;importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("/auth")publicclassAuthController{@AutowiredprivateJwtUtiljwtUtil;@AutowiredprivateAuthenticationManagerauthenticationManager;@AutowiredprivateUserDetailsServiceuserDetailsService;@PostMapping("/login")publicStringlogin(@RequestBodyUseruser){try{authenticationManager.authenticate(newUsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword()));}catch(Exceptione){thrownewRuntimeException("Invalid credentials");}finalUserDetailsuserDetails =userDetailsService.loadUserByUsername(user.getUsername());returnjwtUtil.generateToken(userDetails.getUsername());}}

            八、

          • 跨域:可以在不同的域之间进行身份验证。JWT请求过滤器
          • 六、
          • 请求示例:

            POST /auth/loginContent-Type: application/json{    "username": "user",    "password": "password"}

            响应示例:

            {    "token": "eyJhbGciOiJIUzI1NiIsInR5c..."}
            1. 使用返回的token访问受保护的资源:
            GET /protected/resourceAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c...
        安全配置

        配置Spring Security,以保护API并使用JWT:

        packagecom.example.jwt.config;importcom.example.jwt.filter.JwtRequestFilter;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.config.http.SessionCreationPolicy;importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;importorg.springframework.security.crypto.password.PasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredprivateJwtRequestFilterjwtRequestFilter;@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.csrf().disable().authorizeRequests().antMatchers("/auth/login").permitAll()// 公开登录接口.anyRequest().authenticated()// 其他接口需要认证.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);// 无状态会话// 添加JWT过滤器http.addFilterBefore(jwtRequestFilter,UsernamePasswordAuthenticationFilter.class);}@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("password")).roles("USER");// 示例用户}@BeanpublicPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}}

        七、通过将编码后的header和payload与一个密钥结合,利用指定的算法生成。sub 等)和自定义声明。