SpringSecurity集成JWT

ops/2024/12/22 16:23:48/

使用 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/ops/1821.html

相关文章

虚拟现实(VR)开发框架

虚拟现实&#xff08;VR&#xff09;开发框架为开发者提供了构建VR应用程序所需的基本工具和功能。它们通常包括3D引擎、场景图、输入系统、音频系统和网络功能。下面是一些流行的VR开发框架。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流…

C语言 | Leetcode C语言题解之第24题两两交换链表中的节点

题目&#xff1a; 题解&#xff1a; struct ListNode* swapPairs(struct ListNode* head) {struct ListNode dummyHead;dummyHead.next head;struct ListNode* temp &dummyHead;while (temp->next ! NULL && temp->next->next ! NULL) {struct ListNod…

变更docker的缓存路径

承接上一篇文章&#xff0c;定期清理docker&#xff0c;仍感觉有些累&#xff0c;这个变更一下缓存路径&#xff0c;可以根本解决问题。 linux磁盘清理_docker/overlay2爆满_linux overlay目录满了-CSDN博客 当然&#xff0c;变更docker的缓存路径&#xff0c;也可以使用上一…

OpenHarmony网络组件-Mars

项目简介 Mars 是一个跨平台的网络组件&#xff0c;包括主要用于网络请求中的长连接&#xff0c;短连接&#xff0c;是基于 socket 层的解决方案&#xff0c;在网络调优方面有更好的可控性&#xff0c;暂不支持HTTP协议。 Mars 极大的方便了开发者的开发效率。 效果演示 编译…

vscode搭建C/C++环境

文章目录 一、安装vscode 二、下载安装g 三、安装VSCode插件 四、配置运行环境 一、安装vscode 直接官网免费下载&#xff1a;下载完成后进行安装&#xff0c;记得更换安装路径Visual Studio Code - Code Editing. RedefinedVisual Studio Code is a code editor redefine…

小例子——Flask网站开发

Flask设计上体现了简约而不失灵活的特点它被归类为微框架&#xff08;microframework&#xff09;&#xff0c;因为它有一个简单的核心&#xff0c;用户可以通过扩展来增加其他功能。以下是一些详细介绍&#xff1a;1. 性能与灵活性&#xff1a;Flask以其高性能、灵活性和可扩展…

vue的实现八股

双向绑定原理 Vue的双向绑定原理是通过数据劫持和观察者模式实现的。 vue使用了响应式的对象&#xff0c;即当数据发生改变的时候&#xff0c;视图也会随之改变 数据劫持&#xff1a; vue2使用了object.definedproperty对数据的每个属性进行劫持&#xff0c;从而逐一对每个…

CSS特效---HTML+CSS实现3D旋转卡片

1、演示 2、一切尽在代码中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title&…