基于传统的token认证
用户登录,服务端给返回token,并将token保存在服务端。------>以后用户再来访问时,需要携带token,服务端获取token后,再去数据库中获取token进行校验。
JWT官网:https://jwt.io/
jwt简介
jwt是指JSON Web Token,也就是JSON格式数据使用加密算法加密后按照一定规则生成的一个字符串token 。
官方解释:https://jwt.io/introduction/
jwt试用场景
Authorization(授权):一旦用户登录,后续的每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。
Information Exchange(信息交换):对于安全的在各方面之间的传输信息而言,JWT无疑是一种最好的方式。
jwt的结构
1)Header
header典型是由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或RSA等)
格式如下:
{
"alg": "HS256", //使用HS256加密算法
"typ": "JWT" //表面自己是JWT
}
然后在使用Base64进行编码就得到第一部分
2)Payload
JWT第二部分是payload,信息负载,用来记录主要信息,通信用户以及一些自定义声明
声明分为三种:
1.Registered claims 注册申明
包含用户登陆注册的一些信息,如:iss(发出者),exp(到期时间),sub(主题),aud(受众)等。
2.Public claims 公共申明
这些可以由使用JWT的人员随意定义。 但是为避免冲突,应在IANA JSON Web令牌注册表中定义它们,或将其定义为包含抗冲突名称空间的URI。
3.Private claims 私有申明
这些是自定义声明,旨在在同意使用它们的各方之间共享信息,既不是注册声明也不是公共声明。
格式如:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
注意:payload中尽量不要讲自己的密码放入其中
3) Signature 签名
第三部分,它的值使用的是在**Header**中定义的加密算法,加密前两部分的内容。前两部分按照如下格式组装:
String signature = HMACSHA256(base64UrlEncode(header)+"."+
base64UrlEncode(payload),
secret)
Signature的作用是校验Header和Payload在传输的过程中有没有改变。secret是自定义的签名的私钥,保存在服务端,用于校验token的合法性,并且是唯一的
最后我们最终生成的JWTToken就是三者相连,中间用" . "来连接
String jwtToken = Header +"."+ Payload + "." + Signature ;
在官方网站上,可以进行简单的查看:https://jwt.io/
jwt对数据的解析过程
获取token
第一步:对token进行切割
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
第二步:对第二段进行解密
对第二段进行base64解密,并获取payload 信息,检验token是否过期超时
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022 //发现token的时间
}
第三步:把1,2端合并
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GM75H6uZ-1606294043997)(C:\Users\25769\AppData\Roaming\Typora\typora-user-images\image-20201125164016652.png)]
jwt在Java中的应用
1)导入相关jar包
添加jjwt的jar包:
或者新建一个Maven项目,添加如下依赖:
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jwt.version}</version>
</dependency>
2)创建工具类–JwtUtils
public class JWTUtils {
private static final String TOKEN="#$%^!asas34";
/**
* 获取Token
* @param map
* @return token
*/
public static String getToken(Map<String,Object> map){
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE,7);
JwtBuilder builder= Jwts.builder();
map.forEach((k,v)->{
builder.claim(k,v);
});
//设置过期时间
builder.setExpiration(instance.getTime());
builder.signWith(SignatureAlgorithm.HS256,TOKEN);
return builder.compact();
}
/**
* 验证token 合法性
* @param token
* @return
*/
public static Claims verify(String token){
Claims claims= Jwts.parser().setSigningKey(TOKEN).parseClaimsJws(token).getBody();
return claims;
}
/**
* 获取token的信息
* @param token
* @return
*/
public static Claims getTokenInfo(String token){
Claims claims= Jwts.parser().setSigningKey(TOKEN).parseClaimsJws(token).getBody();
// System.out.println(claims);
// System.out.println("id="+claims.get("userId")); //获取ID
// System.out.println("username="+claims.get("username")); //获取name
// SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
// System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
// System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
// System.out.println("当前时间:"+sdf.format(new Date()) );
return claims;
}
}
3)JWT的简单测试类
public class JwtTest {
public static void main(String[] args) {
Teacher teacher=new Teacher();
teacher.setId(12);
teacher.setName("admin");
Map<String, Object> map = new HashMap<>();
map.put("name",teacher.getName());
String token = JWTUtils.getToken(map);
Claims claims = JWTUtils.getTokenInfo(token);
String name =(String) claims.get("name");
System.out.println("name = " + name);
}
}
测试结果