springboot整合springsecurity+jwt
时间: 2025-06-06 10:31:12 浏览: 13
### Spring Boot 集成 Spring Security 和 JWT 进行身份验证
#### 1. 添加依赖项
为了实现基于JWT的身份验证,在`pom.xml`文件中添加必要的Maven依赖项:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<!-- or jjwt-gson if Gson is preferred -->
<scope>runtime</scope>
<version>0.11.2</version>
</dependency>
```
这些库提供了创建和解析JSON Web Tokens所需的功能[^3]。
#### 2. 创建配置类
定义一个新的Java配置类来设置Spring Security的行为。此类应扩展`WebSecurityConfigurerAdapter`并重写适当的方法以自定义安全策略。
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll() // Allow everyone to access login endpoint
.anyRequest().authenticated(); // All other requests require authentication
http.addFilterBefore(new JwtRequestFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
```
此代码片段禁用了CSRF保护(对于API服务通常不需要),允许未认证用户访问特定路径(如登录接口),并对其他请求强制执行认证检查。此外,还注册了一个过滤器用于处理传入HTTP请求中的JWT令牌验证逻辑。
#### 3. 实现Token生成和服务端点
构建一个控制器用来接收用户名密码形式的凭证,并返回带有有效载荷的新鲜签发token作为响应体的一部分。
```java
@RestController
@RequestMapping("/api/v1/authenticate")
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
}
```
上述方法首先尝试通过传递给它的凭据来进行本地身份验证;成功之后,则加载相应的用户详情信息以便于后续操作——比如在此基础上生成签名后的JWT字符串。
#### 4. 处理客户端发送过来的Token
每当收到含有Authorization头字段且其值以前缀Bearer开头的数据包时,应用应当能够从中提取出实际payload部分进而完成授权流程。
```java
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private MyUserDetailsService myUserDetailsService;
@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);
try {
username = jwtUtil.extractUsername(jwt);
} catch (IllegalArgumentException | ExpiredJwtException e){
logger.warn("Unable to get JWT Token");
}
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.myUserDetailsService.loadUserByUsername(username);
if (Boolean.TRUE.equals(jwtUtil.validateToken(jwt, userDetails))) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request,response);
}
}
```
这段程序会拦截每一个进入系统的网络请求,检查是否存在有效的JWT令牌。如果存在并且合法的话就将其关联到当前线程的安全上下文中去,从而使得受保护资源可以正常工作而不会因为缺少权限而导致失败。
阅读全文
相关推荐


















