1.什么是JWT(json web token)
简单来说是一种令牌(用户访问系统的通行证),该令牌是使用用户的一些非隐私信息经过加密和签名得到的唯一凭证。该令牌由服务器端生成,保存与客户端。
2.JWT组成
JWT由三部分组成:头(header),载荷(payload),签名(signature),然后将这三部分经过加密以后使用点(.)连接起来构成token字符串。
header.payload.signature
例:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibGlseSIsImlkIjoiMSIsImV4cCI6MTY1MDE3ODk2OH0.7S2dZoxCVBcrNjg31SV5u6ngChhoMPIWoh-ZB3kknnw
3.JWT使用
1.普通项目中使用JWT
- 1.使用JWT
所需jar包如下(版本自己选择):
java-jwt-3.10.3.jar
commons-codec-1.10.jar
jackson-core-2.13.1.jar
jackson-databind-2.13.1.jar
jackson-annotations-2.13.1.jar
- 2.使用JJWT
所需jar包如下(版本自己选择):
jjwt-0.9.1.jar
jackson-core-2.13.1.jar
jackson-databind-2.13.1.jar
jackson-annotations-2.13.1.jar
- 3.JWT与JJWT对比
参考网址:https://blog.csdn.net/shaoming314/article/details/121288600
- JJWT是JWT的框架
- JJWT是一个提供端到端的JWT创建和验证的Java库。
- JJWT永远免费和开源。
- JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。
- JJWT的目标是最容易使用和理解用于在JVM上创建和验证JSON Web令牌(JWTs)的库。
- JJWT是基于JWT、JWS、JWE、JWK和JWA RFC规范的Java实现。
- JJWT还添加了一些不属于规范的便利扩展,比如JWT压缩和索赔强制。
- JWT的封装及简单案例(使用JWT)
1.封装:
- JWT的封装及简单案例(使用JWT)
public class JWTUtils {
private static final String SIGNATURE = "千影";
/**
* 生成token header.payload.sign
*/
public static String getToken(Map<String, String> claimParam) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 30); // 默认30秒过期
// 创建jwt builder
Builder builder = JWT.create();
// payload
claimParam.forEach((k, v) -> {
builder.withClaim(k, v);
});
// token过期时间
builder.withExpiresAt(instance.getTime());
// toekn签名
String token = builder.sign(Algorithm.HMAC256(SIGNATURE));
return token;
}
/**
* 验证token合法性
*/
public static boolean verify(String token) {
try {
JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
return true;
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getStackTrace());
return false;
}
}
/**
* 获取token信息方法
*/
public static DecodedJWT getTokenInfo(String token) {
DecodedJWT verify = null;
if(verify(token)) {
verify = JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
}
return verify;
}
}
2.简单案例(模拟登录):
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import com.utils.JWTUtils; // 上面的JWT封装
/***
* 本例旨在模拟用户的登录,以及token认证
* @author harry
*
*/
public class UserLoginToken {
private static final User users[] = new User[] {new User(1, "lily", "abc"), new User(2, "join", "def")};
private static User searchUser(String name, String password) {
User cli = null;
if(!name.isEmpty() && !password.isEmpty()) {
for (User user : users) {
if(user.getName().equals(name.trim()) && user.getPassword().equals(password.trim())) {
cli = user;
}
}
}
return cli;
}
// 登录
public static Map<String, Object> login(String name, String password){
Map<String, Object> resp = new HashMap<String, Object>();
User user = searchUser(name, password);
if(user != null) {
Map<String, String> payload = new HashMap<String, String>();
payload.put("id", user.getId().toString());
payload.put("name", user.getName());
// 生成jwt令牌
String token = JWTUtils.getToken(payload);
resp.put("state", true);
resp.put("msg", "认证成功");
resp.put("token", token);
}else {
resp.put("state", false);
resp.put("msg", "认证失败");
}
return resp;
}
// 访问接口需要token验证
public static Map<String, Object> anythingInterface(String token, String ...args){
Map<String, Object> resp = new HashMap<String, Object>();
System.out.println("当前的token为:" + token);
if(JWTUtils.verify(token)) {
resp.put("state", true);
resp.put("msg", "token验证成功,请合理使用接口");
}else {
resp.put("state", false);
resp.put("msg", "token验证失败,滚蛋!");
}
return resp;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = scan.nextLine();
System.out.println("请输入密码:");
String password = scan.nextLine();
Map<String, Object> resp = UserLoginToken.login(name, password);
System.out.println(resp.toString());
System.out.println("访问接口请携带token令牌...");
String token = resp.get("token").toString();
System.out.println(token);
if(token != null) {
Map<String, Object> resp_verify = UserLoginToken.anythingInterface(token);
System.out.println(resp_verify);
}else {
System.out.println("请拥有token后再来访问接口!");
}
scan.close();
}
}
class User{
private Integer id;
private String name;
private String password;
public User(Integer id, String name, String password){
this.id = id;
this.name = name;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.spring系列使用JWT
由于spring系列已经内嵌了jackson-...,以及其它的一些jar包,故只需引入jwt或者jjwt的pom坐标就可以在项目中使用了,所以此处不赘述spring系列关于jwt的使用
4.JWT使用过程中的一些问题
- 1.在使用JWT和JJWT的时候,我将签名(signature)设置为中文和很长的一段标识,结果发现JJWT出现了数组下标越界的错误,相反,在JWT中是没有这种情况的。
- 2.使用JWT和JJWT的一些方法,二者方法相似但略有不同。
- 3.在JWT的加密和解密的过程中算法得是一样的,要不然会报错,在JJWT中加密算法需要指定,但是解密的时候好像不需要指定(怀疑JJWT自己可以直接识别需要的解密算法?)