SpringSecurity集成JWT

embedded/2024/10/18 14:21:37/

使用 Spring Security 集成 JWT(JSON Web Token)身份验证是一种常见的方式来实现基于令牌的身份验证。在 Spring Boot 应用程序中使用 Spring Security 和 JWT,可以创建一个安全、可扩展的身份验证系统。下面是一个示例,展示如何在 Spring Boot 项目中集成 JWT 身份验证:

1. 添加依赖

首先,在你的 pom.xml 中添加与 JWT 和 Spring Security 相关的依赖:

<dependencies><!-- Spring Boot Starter Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- JJWT (Java JSON Web Token) --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.5</version><scope>runtime</scope></dependency>
</dependencies>

2. 配置 JWT 密钥

application.propertiesapplication.yml 文件中配置用于签署和验证 JWT 的密钥:

properties code

# JWT 配置
jwt.secret=your-secret-key
jwt.expiration-time=86400000 # 令牌有效时间,单位为毫秒
jwt.header=Authorization # JWT 令牌的请求头
jwt.prefix=Bearer # 令牌前缀

3. JWT 工具类

创建一个工具类来生成和解析 JWT:

java">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 JwtTokenUtil {@Value("${jwt.secret}")private String secret;@Value("${jwt.expiration-time}")private long expirationTime;// 生成 JWT 令牌public String generateToken(String username) {Date now = new Date();Date expiryDate = new Date(now.getTime() + expirationTime);return Jwts.builder().setSubject(username).setIssuedAt(now).setExpiration(expiryDate).signWith(SignatureAlgorithm.HS512, secret).compact();}// 解析 JWT 令牌public String getUsernameFromToken(String token) {Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();return claims.getSubject();}// 验证 JWT 令牌是否有效public boolean validateToken(String token, String username) {String tokenUsername = getUsernameFromToken(token);Date expiration = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getExpiration();return (username.equals(tokenUsername) && expiration.after(new Date()));}
}

4. JWT 过滤器

创建一个过滤器,用于在请求中拦截 JWT 令牌,并根据令牌进行身份验证:

java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
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 {@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {String header = request.getHeader("${jwt.header}");if (header != null && header.startsWith("${jwt.prefix} ")) {String token = header.replace("${jwt.prefix} ", "");String username = jwtTokenUtil.getUsernameFromToken(token);if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(token, username)) {UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}}}chain.doFilter(request, response);}
}

5. 配置 Spring Security

SecurityConfig 中配置 Spring Security 来使用 JWT 过滤器:

java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationFilter jwtAuthenticationFilter;@Autowiredprivate UserDetailsService userDetailsService;@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().and().csrf().disable().authorizeRequests().antMatchers("/auth/**").permitAll() // 允许未认证访问登录和注册等路径.anyRequest().authenticated() // 其他请求需要身份验证.and().exceptionHandling().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);// 添加 JWT 过滤器http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);}@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}

6. 登录和令牌颁发

在控制器中实现登录和令牌颁发:

java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/auth")
public class AuthController {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Autowiredprivate UserDetailsService userDetailsService;@PostMapping("/login")public ResponseEntity<?> login(@RequestBody AuthRequest authRequest) {try {// 进行身份验证authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword()));// 加载用户详细信息UserDetails userDetails = userDetailsService.loadUserByUsername(authRequest.getUsername());// 生成 JWT 令牌String token = jwtTokenUtil.generateToken(userDetails.getUsername());// 返回令牌return ResponseEntity.ok(new AuthResponse(token));} catch (BadCredentialsException e) {return ResponseEntity.status(401).body("Invalid credentials");}}
}

数据模型:

  • AuthRequest:表示登录请求,包括用户名和密码。
  • AuthResponse:表示登录响应,包括生成的 JWT 令牌。
java">// 登录请求数据模型
public class AuthRequest {private String username;private String password;// Getters and setters...
}// 登录响应数据模型
public class AuthResponse {private String token;public AuthResponse(String token) {this.token = token;}// Getters and setters...
}

通过以上配置和代码,你可以在 Spring Boot 项目中集成 JWT 身份验证。你可以根据自己的需求进一步定制和优化。


http://www.ppmy.cn/embedded/9559.html

相关文章

Vue2+ElementUI的el-table实现新增数据行与删除的功能

Vue2ElementUI的el-table实现新增数据行与删除的功能 文章目录 Vue2ElementUI的el-table实现新增数据行与删除的功能1. 代码2. 效果 1. 代码 TableIndex.vue如下 <template><div><div><el-button click"add" class"filter-item" pl…

2024接口自动化测试入门基础知识【建议收藏】

接口自动化测试是指通过编写测试脚本和使用相关工具&#xff0c;对软件系统的接口进行自动化测试的过程。 今天本文从4个方面来介绍接口自动化测试入门基础知识 一、接口自动化测试是什么&#xff1f; 二、接口自动化测试流程&#xff1f; 三、接口自动化测试核心知识点有那些…

Golang:三种引号详解-单引号、双引号、反引号

Golang限定字符或者字符串一共三种引号&#xff1a; 单引号&#xff08;)&#xff0c;单个字符&#xff0c;更类似于C语言中的char类型&#xff0c; 双引号("") &#xff0c;字符串&#xff0c;单行的&#xff0c;多个字符&#xff08;字母数字&#xff09;。 反引…

后端获取请求体Body,将请求体进行解密放回Request请求,并能通过@RequestBody获取

目前系统发送的post和put请求都是没有加密数据。客户需要将请求体加密。而系统已经基本开发完成&#xff0c;不可能一个一个去修改发送的请求。就需要在发送请求时候在拦截器中将body进行加密。并且在后端进行请求过滤解密&#xff0c;并且能通过RequestBody继续获取对象。 1.…

前端学习之DOM编程案例:点名案例和秒表案例

点名 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>点名案例</title><style>*{margin: 0;padding: 0;}</style> </head> <body><div id"container">…

软件行业中的蓝海领域有哪些?

一、什么是蓝海&#xff1f; 蓝海&#xff0c;指的是未知的市场空间。这个概念相对于“红海”而言&#xff0c;红海则是指已知的市场空间。 企业要启动和保持获利性增长&#xff0c;就必须超越产业竞争&#xff0c;开创全新市场&#xff0c;这其中包括两块&#xff1a;一块是…

【三维地图无人机路径规划】基于改进A星算法

课题名称&#xff1a; 基于改进A星算法的无人机三维地图路径规划 版本时间&#xff1a; 2024-04-22 程序运行&#xff1a; 直接运行AStar.m 文件即可 代码获取方式&#xff1a; QQ&#xff1a;491052175 VX&#xff1a;Matlab_Lover 改进方向&#xff1a; 预估函数增…

【学习笔记】Vue3源码解析:第三部分-获取computed的值;实现computed

课程地址&#xff1a;【已完结】全网最详细Vue3源码解析&#xff01;&#xff08;一行行带你手写Vue3源码&#xff09; 第三部分-获取computed的值&#xff1b;实现computed&#xff1a;&#xff08;对应课程的第18-21节&#xff09; 第22节&#xff1a;《获取computed的值》 …