Spring Security如何进行jwt验证配置
时间: 2024-02-22 13:30:51 浏览: 291
Spring Security可以通过配置JWT(JSON Web Token)来实现身份验证。以下是一个简单的Spring Security JWT配置示例:
1. 添加依赖
在pom.xml文件中添加以下依赖:
```xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
```
2. 创建JWT工具类
创建一个JWT工具类,用于创建和解析JWT令牌。以下是一个简单的实现示例:
```java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
public class JwtUtil {
private final String SECRET_KEY = "secret";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
List<String> authorities = userDetails.getAuthorities().stream()
.map(authority -> authority.getAuthority())
.collect(Collectors.toList());
claims.put("roles", authorities);
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
long currentTimeMillis = System.currentTimeMillis();
long expirationTimeMillis = currentTimeMillis + 1000 * 60 * 60; // token有效期为1小时
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(currentTimeMillis))
.setExpiration(new Date(expirationTimeMillis))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public boolean isTokenValid(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public List<SimpleGrantedAuthority> getAuthoritiesFromToken(String token) {
List<String> roles = getClaimFromToken(token, claims -> claims.get("roles", List.class));
return roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
}
}
```
3. 创建Spring Security配置类
创建一个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.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
```
在上面的配置中,我们使用了`JwtAuthenticationEntryPoint`类和`JwtRequestFilter`类,这两个类是JWT身份验证的核心组件。`JwtAuthenticationEntryPoint`类用于处理身份验证异常,而`JwtRequestFilter`类用于拦截请求并验证身份验证令牌。
4. 创建JwtAuthenticationEntryPoint类
创建一个JwtAuthenticationEntryPoint类,用于处理身份验证异常。以下是一个简单的实现示例:
```java
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
```
5. 创建JwtRequestFilter类
创建一个JwtRequestFilter类,用于拦截请求并验证身份验证令牌。以下是一个简单的实现示例:
```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.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 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.getUsernameFromToken(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
在上面的实现中,我们获取从请求头中获取JWT令牌并验证其有效性。如果JWT令牌有效,则将用户详细信息添加到Spring Security上下文中。
6. 创建JwtAuthenticationController类
创建一个JwtAuthenticationController类,用于处理身份验证请求。以下是一个简单的实现示例:
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JwtAuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@PostMapping("/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest jwtRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(jwtRequest.getUsername(), jwtRequest.getPassword()));
} catch (AuthenticationException e) {
throw new Exception("Incorrect username or password", e);
}
UserDetails userDetails = userDetailsService.loadUserByUsername(jwtRequest.getUsername());
String token = jwtUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
}
```
在上面的实现中,我们使用`AuthenticationManager`进行身份验证。如果身份验证成功,则使用`JwtUtil`生成JWT令牌并将其返回给客户端。
完成了以上步骤后,就可以使用JWT进行身份验证了。
阅读全文