SpringSecurity集成JWT

devtools/2024/9/23 10:29:16/

使用 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/devtools/9079.html

相关文章

【Flutter】GetX状态管理及路由管理用法

目录 一、安装二、使用1.安装GetX插件&#xff0c;快捷生成模版代码2.主入口MaterialApp改成GetMaterialApp3.定义路由常量RoutePath类、别名映射页面RoutePages类4. 初始initialRoute&#xff0c;getPages。5.调用 总结 一、安装 dependencies: get: ^4.6.6二、使用 1.安装G…

Linux 网络操作命令FTP

FTP命令 引言 文件传输协议&#xff08;FTP&#xff09;是一种用于在网络上进行文件传输的协议。在Linux系统中&#xff0c;FTP可以作为一个非常有用的工具来上传、下载和管理文件。本文将介绍如何在Linux系统中安装FTP服务器&#xff0c;以及如何使用FTP客户端进行文件传输。…

Redis中set数据类型详解

SADD key member [member …] summary: Add one or more members to a set since: 1.0.0 SCARD key summary: Get the number of members in a set since: 1.0.0 SDIFF key [key …] summary: Subtract multiple sets since: 1.0.0 SDIFFSTORE destination key [key …] sum…

从 Android 恢复已删除文件的 3 种简单方法

如何从 Android 恢复已删除的文件&#xff1f;毫不犹豫&#xff0c;有些人可能会认为从 Google 备份恢复 Android 文件太容易了。但是&#xff0c;如果删除的文件未同步到您的帐户或未备份怎么办&#xff1f;您错误的恢复可能会永久删除您想要的数据。因此&#xff0c;我们发布…

[Meachines][Easy]Devvortex

Main $ nmap -p- 10.10.11.242 --min-rate 1000 # echo 10.10.11.242 devvortex.htb>>/etc/hosts 子域名爆破 $ apt install seclists $ wfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://devvortex.htb/" -H &…

【Linux基础】Linux基础概念

目录 前言 浅谈什么是文件&#xff1f; Linux下目录结构的认识及路径 目录结构 路径 家目录 什么是递归式的删除 重定向 输出重定向&#xff1a; 追加重定向&#xff1a; 输入重定向&#xff1a; 命令行管道 shell外壳 为什么需要shell外壳&#xff1f; shell外壳…

网络工程师----第四天

DNS DNS含义&#xff1a; DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;&#xff0c;因特网上作为域名和IP地址互相映射的一个分布式数据库&#xff0c;能够使用户更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。通过主机名&a…

Excel VBA技术:编织数据之梦的魔法语言

想要让你的Excel技能瞬间升级&#xff0c;成为数据处理与展示的顶尖高手吗&#xff1f;Excel VBA技术正是你不可错过的魔法武器&#xff01;它能让你轻松驾驭复杂的数据任务&#xff0c;自动化处理繁琐操作&#xff0c;释放你的双手和大脑。通过VBA&#xff0c;你可以创建精美的…