以下是“SpringBoot使用JWT实现登录验证的方法示例”的完整攻略:
1. 什么是JWT?
JWT(JSON Web Token)是由JSON生成的令牌,通常用于身份验证和授权。它是一个开放标准(RFC 7519),通过在不同方之间安全地传输声明来作为JSON Web签名(JWS)或JSON Web加密(JWE)的方式。在Spring Boot中使用JWT可以达到一定的安全验证。
2. JWT的结构
一个JWT令牌由3个部分组成:
头部(Header)
头部包含了令牌的元数据,它包括了算法和类型等信息。例子:
{
"alg": "HS256",
"typ": "JWT"
}
负载(Payload)
负载包含了一些声明信息,比如用户ID,有效期时间等等。例子:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
签名(Signature)
签名是对头部和负载进行签名的结果。根据头部中声明的算法和一个密钥,可以通过特殊的算法来生成一个签名。
3. Spring Boot使用JWT实现登录验证的方法示例
3.1 创建Spring Boot项目
首先,我们需要创建一个Spring Boot 项目。可以使用Spring Initializr 或是手动创建。
3.2 添加依赖
然后,我们需要添加依赖,包括 Spring Security 和JWT。在maven中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
3.3 实现UserDetailsService
接下来,我们需要实现一个Spring Security的UserDetailsService接口,用来根据用户名获取用户信息:
/**
* Spring Security UserDetailsService 实现类
* 用于获取用户信息
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
} else {
return JwtUserFactory.create(user);
}
}
}
3.4 创建JwtUtils
然后,我们需要创建一个JwtUtils类,用来生成和解析JWT令牌:
/**
* JWT工具类,用来生成和解析JWT
*/
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expires}")
private long expiration;
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(Claims.SUBJECT, userDetails.getUsername());
claims.put(Claims.ISSUED_AT, new Date());
return generateToken(claims);
}
public String generateToken(Map<String, Object> claims) {
Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000);
return Jwts.builder()
.setClaims(claims)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public String getUsernameFromToken(String token) {
return getClaimsFromToken(token).getSubject();
}
public Date getExpirationDateFromToken(String token) {
return getClaimsFromToken(token).getExpiration();
}
public Claims getClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
public boolean isTokenExpired(String token) {
Date expirationDate = getExpirationDateFromToken(token);
return expirationDate.before(new Date());
}
}
3.5 实现AuthenticationController
最后,我们需要实现一个AuthenticationController,用来处理登录认证,并生成JWT令牌:
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private JwtUtils jwtUtils;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) throws AuthenticationException {
// 验证用户和密码
UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, loginRequest.getPassword());
authenticationManager.authenticate(authenticationToken);
// 生成JWT令牌
String token = jwtUtils.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(token));
}
}
class LoginRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
class AuthenticationResponse {
private final String token;
public AuthenticationResponse(String token) {
this.token = token;
}
public String getToken() {
return token;
}
}
到此处,整个登录认证的流程就完成了。
3.6 示例使用
3.6.1 登录
使用POST方式请求URL:"/auth/login",传递参数如下:
{
"username":"admin",
"password":"admin"
}
请求成功,将会得到类似如下的响应:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTYwNTQyMjQwNiwiZXhwIjoxNjA1NDIzMjA2fQ.om7Bvu_ikvUT6eUrJ67x9yvLsaJk3de-5Lb5mzyZ7fg"
}
3.6.2 调用受保护接口
修改我们的UserController:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/info")
public String getInfo(@AuthenticationPrincipal JwtUserDetails auth) {
return "username: " + auth.getUsername() + ", id: " + auth.getId();
}
}
提供一个受保护的接口"/user/info",在方法参数中使用 "@AuthenticationPrincipal JwtUserDetails" 注解,即可获取当前登录用户的信息。
使用POST方式请求URL:"/auth/login"获取到的Token,构造一个新的Get请求Header: "Authorization",值为:"Bearer {token}",其中 {token} 为从服务器获取到的 Token 串,发送到URL:"/user/info"即可获取当前用户的信息。
这样,我们就实现了一个简单的使用JWT的Spring Boot登录认证流程。
4. 总结
以上就是实现基于SpringBoot + JWT的登录认证流程的详细攻略。JWT具有可扩展性、轻量级、安全性高等特点,在实际开发中也是比较常见的身份验证方式之一。通过以上的方式,你也可以轻松实现一个SpringBoot + JWT的登录认证功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot使用JWT实现登录验证的方法示例 - Python技术站