springboot集成springsecurity jwt示例
时间: 2023-06-30 14:24:20 浏览: 215
springboot整合security与jwt
好的,下面是一个简单的 Spring Boot 集成 Spring Security 和 JWT 的示例:
1. 添加依赖
在项目的 pom.xml 文件中添加以下依赖:
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
```
2. 配置 Spring Security
在 Spring Boot 项目中,可以通过配置类来配置 Spring Security。创建一个继承自 WebSecurityConfigurerAdapter 的配置类,并重写 configure 方法:
```
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
```
上述代码中,我们配置了一个用户详细信息服务 MyUserDetailsService,并将其注入到 AuthenticationManagerBuilder 中。此外,我们还配置了一个 BCryptPasswordEncoder,用于加密用户的密码。
我们还配置了一个 HttpSecurity 对象,用于定义 Spring Security 的策略。在这里,我们允许任何人访问 /authenticate 接口,并要求其他接口进行身份验证。我们还配置了一个 JwtRequestFilter,用于检查 JWT 是否有效,并将其添加到过滤器链中。
3. 实现用户详细信息服务
我们需要实现一个用户详细信息服务 MyUserDetailsService,用于从数据库中获取用户信息。创建一个实现了 UserDetailsService 接口的类,并重写 loadUserByUsername 方法:
```
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<User> userOptional = userRepository.findByUsername(username);
userOptional.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
return userOptional.map(MyUserDetails::new).get();
}
}
```
上述代码中,我们使用 UserRepository 来从数据库中获取用户信息,并将其转换为 UserDetails 对象。
4. 实现 JWT 工具类
我们需要实现一个 JWT 工具类 JwtUtil,用于生成和验证 JWT。创建一个实现了 Serializable 接口的类 JwtUtil:
```
@Component
public class JwtUtil implements Serializable {
private static final long serialVersionUID = -2550185165626007488L;
public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
@Value("${jwt.secret}")
private String secret;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
```
上述代码中,我们使用了 JJWT 库来生成和验证 JWT。我们定义了一些方法来获取 JWT 中的信息,以及生成和验证 JWT。
5. 实现 JWT 请求过滤器
我们需要实现一个 JWT 请求过滤器 JwtRequestFilter,用于检查 JWT 是否有效。创建一个实现了 OncePerRequestFilter 接口的类 JwtRequestFilter:
```
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private MyUserDetailsService 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.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
上述代码中,我们使用了 OncePerRequestFilter 接口来实现一个请求过滤器。在 doFilterInternal 方法中,我们检查 Authorization 头是否存在,并从中获取 JWT。如果 JWT 有效,则将其添加到 Spring Security 的上下文中。
6. 创建控制器
最后,我们创建一个控制器 FileController,用于处理文件的上传和下载请求。创建一个加了 @RestController 注解的类 FileController:
```
@RestController
public class FileController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file,
@RequestHeader("Authorization") String authorizationHeader) {
String jwt = authorizationHeader.substring(7);
String username = jwtUtil.getUsernameFromToken(jwt);
// TODO: 上传文件的逻辑
return ResponseEntity.ok("File uploaded successfully.");
}
@GetMapping("/download")
public void downloadFile(HttpServletResponse response, @RequestHeader("Authorization") String authorizationHeader) {
String jwt = authorizationHeader.substring(7);
String username = jwtUtil.getUsernameFromToken(jwt);
// TODO: 下载文件的逻辑
}
}
```
上述代码中,我们创建了两个接口,一个用于上传文件,一个用于下载文件。在这里,我们检查 Authorization 头是否存在,并从中获取 JWT。如果 JWT 有效,则继续执行相应的逻辑。
这就是一个简单的 Spring Boot 集成 Spring Security 和 JWT 的示例。
阅读全文