为了在Java中使用JWT生成Token进行接口鉴权,我们需要以下步骤:
1. 引入依赖
我们需要在项目中引入一个JWT依赖,例如Java JWT(https://github.com/auth0/java-jwt)。
Maven坐标如下:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
2. 生成Token
我们可以使用如下代码在Java中生成一个JWT Token:
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
public class JWTUtils {
/**
* 生成JWT Token
* @param issuer 签发人
* @param subject 主题
* @param expireSeconds 过期时间,单位为秒
* @param secret 密钥
* @return JWT Token
*/
public static String generateToken(String issuer, String subject, long expireSeconds, String secret) {
// 设置过期时间
Date expireDate = new Date(System.currentTimeMillis() + expireSeconds * 1000);
// 设置Header
Map<String, Object> header = new HashMap<>();
header.put("alg", "HS256");
header.put("typ", "JWT");
// 生成Token
String token = JWT.create().
withHeader(header).
withIssuer(issuer).
withSubject(subject).
withExpiresAt(expireDate).
sign(Algorithm.HMAC256(secret));
return token;
}
}
其中,参数分别表示:
- issuer:签发人
- subject:主题
- expireSeconds:过期时间,单位为秒
- secret:密钥
使用JWT生成Token的算法一般采用HMAC加密算法,常见的有HMAC256和HMAC512。
为方便演示,我们在主函数中调用该方法并输出生成的Token:
public class Main {
public static void main(String[] args) {
String issuer = "test";
String subject = "test-token";
long expireSeconds = 3600;
String secret = "my-secret"; // 这里应该放在配置文件中,不应该明文写在代码中
String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
System.out.println(token);
}
}
输出的Token如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0Iiwic3ViIjoidGVzdC10b2tlbiIsImV4cCI6MTQ4MzAwNjc5MX0.9qCZ9UBpE5Jk8VTDeYACScJf_kwSp-CWr5zgG-Dgys4
3. 验证Token
我们可以使用如下代码在Java中验证一个JWT Token:
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JWTUtils {
/**
* 验证JWT Token
* @param token JWT Token
* @param secret 密钥
* @return 是否验证通过
*/
public static boolean verifyToken(String token, String secret) {
try {
// 创建验证器并设置Issuer和密钥
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("test")
.build();
// 验证Token
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {
return false;
}
}
}
验证Token的时候需要进行以下几项检验:
- 是否有效(例如过期或者被篡改)
- 是否由合法的签发人签发
- 是否由合法的密钥签名
同样,我们在主函数中调用该方法并输出验证结果:
public class Main {
public static void main(String[] args) {
String issuer = "test";
String subject = "test-token";
long expireSeconds = 3600;
String secret = "my-secret"; // 这里应该放在配置文件中,不应该明文写在代码中
String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
boolean result = JWTUtils.verifyToken(token, secret);
System.out.println(result);
}
}
输出的结果为:
true
示例1
我们可以将上述两个步骤结合起来并应用于一个简单的接口鉴权上,示例代码如下:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
private String secret = "my-secret";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 获取Authorization Header
String authorization = request.getHeader("Authorization");
if (authorization == null || authorization.isEmpty()) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
// 校验Token
try {
// 创建验证器并设置Issuer和密钥
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("test")
.build();
// 验证Token
DecodedJWT jwt = verifier.verify(authorization);
return true;
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
}
该示例定义了一个拦截器,在请求进入Controller之前验证JWT Token的有效性。如果Token验证通过则放行,否则返回401 Unauthorized错误。
示例2
我们可以将JWT生成Token的代码应用于一个实际的业务场景中,例如在用户登录成功后生成一个Token并返回给客户端,客户端在后续请求中携带该Token以进行接口鉴权。
该示例利用Spring Boot框架搭建,代码如下:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody UserCredentials credentials) {
// 根据用户名和密码从数据库中查询用户信息
User user = userService.getUserByCredentials(credentials.getUsername(), credentials.getPassword());
if (user == null) {
return ResponseEntity.badRequest().body("用户名或密码错误");
}
// 生成Token并返回给客户端
String issuer = "test";
String subject = String.format("user-%d", user.getId());
long expireSeconds = 3600;
String secret = "my-secret";
String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
return ResponseEntity.ok(token);
}
@GetMapping("/profile")
public ResponseEntity<User> getProfile(HttpServletRequest request) {
// 从Token中解析出用户ID
int userId = getUserIdFromToken(request);
if (userId <= 0) {
return ResponseEntity.badRequest().build();
}
// 根据用户ID从数据库中查询用户信息
User user = userService.getUserById(userId);
if (user == null) {
return ResponseEntity.notFound().build();
}
// 返回用户信息
return ResponseEntity.ok(user);
}
private int getUserIdFromToken(HttpServletRequest request) {
// 从Authorization Header中解析出Token
String authorization = request.getHeader("Authorization");
if (authorization == null || authorization.isEmpty()) {
return -1;
}
String token = authorization.substring("Bearer ".length());
// 解析Token,获取UserId
try {
DecodedJWT jwt = JWT.decode(token);
String subject = jwt.getSubject();
int userId = Integer.parseInt(subject.split("-")[1]);
return userId;
} catch (Exception e) {
return -1;
}
}
}
该示例中,客户端需要先调用“/user/login”接口进行登录,登录成功后服务器会返回一个JWT Token;客户端在后续的请求中需要在Authorization Header中携带该Token,例如:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0Iiwic3ViIjoidXNlci0xIiwiZXhwIjoxNDgzMDAyNjUwfQ.Ykn7x8K0Vwlf2kfjFMnLqmaA0O4SpnJHp3aY5oDtKZs
服务器在接收到请求后会校验Token的有效性,并从Token中解析出用户ID,再使用该用户ID从数据库中查询用户信息并返回给客户端。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中使用JWT生成Token进行接口鉴权实现方法 - Python技术站