一、什么是JWT
JSON Web Token (JWT)是一种安全的,开放的标准(RFC 7519),用于在双方之间传输信息。JWT包含了三部分,分别是Header,Payload和Signature。
Header通常包含两部分,算法和类型。算法指定加密算法,类型指定JWT类型,最常见的是JWT。
Payload是JWT最重要的部分,包含了Claim,Claim是要传输的数据,常见的有:iss(Issuer),iat(Issued At),exp(Expiration Time),sub(Subject),aud(Audience)等,Claim可以被加密。
Signature是将Header和Payload进行加密后的结果,Signature的作用是验证JWT的合法性。
二、在Spring Boot中使用JWT
1. 引入依赖
在pom.xml中添加以下依赖,这里使用的是io.jsonwebtoken:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 创建JWT工具类
我们需要创建一个工具类来生成和验证JWT,其中包含了JWT的生成和解析方法。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
private Key key;
@PostConstruct
public void init() {
key = Keys.hmacShaKeyFor(secret.getBytes());
}
public String generateToken(String username, String role) {
Map
claims = new HashMap<>();
claims.put("username", username);
claims.put("role", role);
return Jwts.builder()
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(key, SignatureAlgorithm.HS512)
.compact();
}
public Claims parseToken(String token) {
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
}
}
3. 创建登录和鉴权接口
我们需要创建一个/login接口来进行用户登录,使用POST方法提交用户名和密码,之后验证用户信息,生成JWT并返回给客户端。还需要创建一个校验接口,使用JWT进行鉴权,如果JWT合法,返回200,否则返回401。
@RestController
public class AuthController {
@Autowired
private JwtUtils jwtUtils;
@PostMapping("/login")
public ResponseEntity
login(@RequestBody User user) {
if ("admin".equals(user.getUsername()) && "123456".equals(user.getPassword())) {
String token = jwtUtils.generateToken(user.getUsername(), "admin");
return ResponseEntity.ok(token);
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
@GetMapping("/auth")
public ResponseEntity auth(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (StringUtils.isBlank(token)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
try {
Claims claims = jwtUtils.parseToken(token);
String username = claims.get("username", String.class);
String role = claims.get("role", String.class);
return ResponseEntity.ok().build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
}
三、JWT的安全性
JWT的安全性很大一部分依赖于secret(加密密钥)的安全性,由于JWT是可解密的,所以secret在使用中要严格保密。另外,JWT也有一些缺点:
- JWT不适合存储敏感数据。
- 如果一个JWT被盗用,那么所有在有效期内的请求都是可以通过的,因此我们需要设置JWT的有效期尽量短。
- JWT无法撤销,如果需要取消某个JWT的访问授权,需要等待其过期或者在服务端的黑名单上维护该JWT。
四、小结
通过本文,我们了解了JWT的结构和原理,掌握了在Spring Boot中使用JWT的方法,并介绍了JWT的安全性和一些限制。在实际的项目中,我们可以根据具体的需求选择合适的鉴权方式,在保障系统安全的前提下,提高用户体验。