乐闻世界logo
搜索文章和话题

How can you secure REST APIs in a Spring Boot application using JSON Web Tokens ( JWT )?

1 个月前提问
1 个月前修改
浏览次数12

1个答案

1

在Spring Boot应用程序中保护REST API通常涉及几个关键步骤,使用JSON Web Token(JWT)是其中一个非常有效的策略。下面我将详细解释如何做到这一点,并提供一些代码示例来阐明实现过程。

步骤 1: 引入JWT库

首先,需要在Spring Boot项目的pom.xml文件中添加JWT库依赖。jjwt是一个流行的Java库,用于创建和验证JWTs。例如:

xml
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>

步骤 2: 创建JWT工具类

创建一个工具类JwtUtil来处理JWT的生成和验证。这个类将负责:

  • 生成一个令牌
  • 验证令牌的有效性
  • 从令牌中提取信息(如用户名)
java
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.function.Function; public class JwtUtil { private String secretKey = "your_secret"; public String extractUsername(String token) { return extractClaim(token, Claims::getSubject); } public Date extractExpiration(String token) { return extractClaim(token, Claims::getExpiration); } public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); } private Claims extractAllClaims(String token) { return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); } private Boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } public String generateToken(String username) { return Jwts.builder().setSubject(username) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) .signWith(SignatureAlgorithm.HS256, secretKey).compact(); } public Boolean validateToken(String token, String username) { final String extractedUsername = extractUsername(token); return (username.equals(extractedUsername) && !isTokenExpired(token)); } }

步骤 3: 实现JWT请求过滤器

创建JwtRequestFilter类继承OncePerRequestFilter,在此过滤器中对传入的请求进行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.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; public class JwtRequestFilter extends OncePerRequestFilter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtUtil jwtUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); username = jwtUtil.extractUsername(jwt); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (jwtUtil.validateToken(jwt, userDetails.getUsername())) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } } chain.doFilter(request, response); } }

步骤 4: 配置Spring Security

将JWT过滤器集成到Spring Security配置中。这需要在Spring Security配置类中添加JWT过滤器,并配置HTTP安全以只允许带有有效JWT的请求访问受保护的端点。

java
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; @EnableWebSecurity public class SecurityConfigurer extends WebSecurityConfigurerAdapter { @Autowired private JwtRequestFilter jwtRequestFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests().antMatchers("/authenticate").permitAll() .anyRequest().authenticated() .and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } }

步骤 5: 测试和部署

最后,通过编写测试用例来验证JWT的实现,并在开发或生产环境中部署应用程序。

利用JWT进行身份验证和授权,我们能够确保只有拥有有效令牌的用户才能访问受保护的资源,从而增强了应用程序的安全性。

2024年8月16日 00:49 回复

你的答案