赞
踩
使用 Spring Security 集成 JWT(JSON Web Token)身份验证是一种常见的方式来实现基于令牌的身份验证。在 Spring Boot 应用程序中使用 Spring Security 和 JWT,可以创建一个安全、可扩展的身份验证系统。下面是一个示例,展示如何在 Spring Boot 项目中集成 JWT 身份验证:
首先,在你的 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>
在 application.properties
或 application.yml
文件中配置用于签署和验证 JWT 的密钥:
properties code
- # JWT 配置
- jwt.secret=your-secret-key
- jwt.expiration-time=86400000 # 令牌有效时间,单位为毫秒
- jwt.header=Authorization # JWT 令牌的请求头
- jwt.prefix=Bearer # 令牌前缀
创建一个工具类来生成和解析 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 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()));
- }
- }
创建一个过滤器,用于在请求中拦截 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.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 {
-
- @Autowired
- private JwtTokenUtil jwtTokenUtil;
-
- @Autowired
- private UserDetailsService userDetailsService;
-
- @Override
- protected 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);
- }
- }
在 SecurityConfig
中配置 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.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 {
-
- @Autowired
- private JwtAuthenticationFilter jwtAuthenticationFilter;
-
- @Autowired
- private UserDetailsService userDetailsService;
-
- @Bean
- public BCryptPasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
-
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
- }
-
- @Override
- protected 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
- @Bean
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
- }
- }
在控制器中实现登录和令牌颁发:
- 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 {
-
- @Autowired
- private AuthenticationManager authenticationManager;
-
- @Autowired
- private JwtTokenUtil jwtTokenUtil;
-
- @Autowired
- private 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 令牌。- // 登录请求数据模型
- 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 身份验证。你可以根据自己的需求进一步定制和优化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。