要實現SpringBoot結合JWT實現用戶登錄功能,可以按照以下步驟進行操作:
pom.xml
文件中添加Spring Security和JWT的依賴。<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>
public class User {
private String username;
private String password;
// getter and setter
}
UserDetailsService
接口的用戶認證服務類,用于加載用戶信息。@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 從數據庫或其他數據源加載用戶信息
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
}
}
@RestController
public class LoginController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody User user) {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
String token = jwtUtils.generateToken(user.getUsername());
return ResponseEntity.ok(token);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
}
@Component
public class JwtUtils {
private final String secret = "your-secret-key";
private final long expiration = 86400000;
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean isTokenValid(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private boolean isTokenExpired(String token) {
Date expirationDate = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getExpiration();
return expirationDate.before(new Date());
}
}
application.properties
文件中配置Spring Security的相關屬性。spring.security.user.name=admin
spring.security.user.password=admin
spring.security.user.roles=USER,ADMIN
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String header = request.getHeader("Authorization");
if (StringUtils.hasText(header) && header.startsWith("Bearer ")) {
String token = header.substring(7);
String username = jwtUtils.getUsernameFromToken(token);
if (StringUtils.hasText(username) && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtils.isTokenValid(token, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
}
filterChain.doFilter(request, response);
}
}