JWT
定义:
Json web token 是一个开发标准,它定义了一种紧凑且自包含的方式,用于在各方之间安全地将信息作为json对象传输。
由于此信息是经过数字签名的,因此可以被验证和信任。可以使用密钥(HMAC算法)或使用RSA的公/私钥对JWT进行签名。
了解下定义的一些概念:
紧凑:由于其大小,它可以通过url,post参数或Http表头发送。另外,由于其内存空间较小,其传输速度很快。
自包含:有效负载包含有关用户的所有必须信息,以避免多次查询数据库或者查询相关缓存带来的相关性能问题。
什么时候使用JSON WEB令牌?
在以下情况下,JSON WEB令牌很有用:
身份验证:这是使用JWT的典型方案,一旦用户登录,每个后续的请求都将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以很轻松的不同域的系统中使用。
信息交换:JWT在各方面之间安全的传输信息的一种好方法,因为可以对他们进行签名,因此可以确定发送者是他们所说身份。此外,由于签名是使用标头和有效负载计算的,因此可以验证内容有没有被进行修改。
JSON WEB令牌结构是什么?
JWT由三部分组成,每一部分之间用(.)进行分割,分别是:
标头
有效负载
签名
因此JWT通常内容如下所示:
xxxx.yyyyy.zzzzz
标头:
通常有两部分组成:令牌的类型(即JWT)和哈希算法(例如:HMAC SHA256或者RSA)
例如:
{
"alg": "HS256",
"typ": "JWT"
}
有效负载:
令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他元数据的声明。有三种类型的声明:保留 公共 和私有声明
1.保留:这些是一组预定义的权利要求,不是强制性的,而是建议使用的,它们被认为可以提供一组有用的,可互操作的权利要求。其中一些是:iss(发行者),exp(到期时间),sub(主题), aud(受众)等等。
请注意,声明名称仅是三个字符,因为JWT是紧凑的。
2.公共声明:使用JWT的人员可以随意定义这些声明。
3.私人声明:这些是为在同意使用它们的各方之间共享信息而创建的自定义声明。
有效负载的示例可能是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对有效负载进行Base64Url编码,以形成JWT的第二部分。
签名
要创建签名部分,您必须获取编码的标头,编码的有效负载,密钥,标头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,则将以以下方式创建签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
该签名用于验证JWT的发件人是谁,并确保该消息没有以这种方式更改。
放在一起
输出是由点分隔的三个Base64字符串,这些字符串可以在HTML和HTTP环境中轻松传递,并且与基于XML的标准(例如SAML)相比更加紧凑。
下图显示了一个JWT,它已对先前的标头和有效负载进行了编码,并用一个秘密进行了签名。
JSON WEB令牌如何工作?
在身份验证中,当用户使用其凭据成功登录时,将返回JSON web令牌。由于令牌是凭据,因此必须格外小心以防止安全问题。
通常,令牌的保留时间不应该超过要求的时间。
由于缺乏安全性,您也不应该将敏感的会话数据存储在浏览器中。
每当用户想要访问受保护的路由时,通常应该Bearer模式下的Authorization header中发送JWT。因此,标头的内容如下所示:
Authorization: Bearer <token>
这是一种无状态的身份验证机制,因为用户状态永远不会保存在服务器的内存中。服务器的受保护路由将在Authorization标头中检查有效的JWT,如果存在,则将允许该用户。由于JWT是独立的,因此所有必须的信息都在其中,从而减少了往返数据库的需求。
这允许完全无状态的数据API,甚至可以向下游服务器发送请求,哪个域为您的api服务都没有关系,因为跨域资源共享cors不会使用cookie,因此不会成为问题。
为什么要使用JSON web令牌呢?
JSON WEB 令牌与简单web令牌 SWT 和安全性声明标记语言令牌SAML相比的优势。
由于JSON不如xml冗长,因此在编码时,它的大小也较小,使得JWT比SAML更紧凑。这使得JWT是在HTML和HTTP环境中传递的不错的选择.
在安全方面,只能使用HMAC算法由共享密钥对SWT进行对称签名。同时JWT和SAML令牌还可以使用X.509证书形式的公共/私有密钥对其进行签名。但是与简单签名JSON相比,使用XML Digital Signature签名XML而不引入模糊的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象,相反,XML没有自然的文档到对象的映射。这使得使用JWT比使用SAML断言更加容易。
关于用法,JWT是在Internet规模上使用的。这突出了在多个平台(尤其是移动平台)上对JWT进行客户端处理的简便性。
我们如何在AUTH0中使用JSON WEB令牌?
在Auth0中,由于身份验证过程,我们发出了JWT。当用户使用Auth0登录时,将创建,签名JWT并将其发送给用户。Auth0支持使用HMAC和RSA算法签名JWT。然后,此令牌将用于通过API进行身份验证和授权,这些API将授予对其受保护的路由和资源的访问权限。
我们还使用JWT在Auth0的API v2中执行身份验证和授权,以取代常规的不透明API密钥的传统用法。关于授权,JSON Web令牌允许细粒度的安全性,即在令牌中指定一组特定权限的能力,从而提高了可调试性。
简单介绍下创建,解析和验证,已经验证过,具体根据自己的场景来进行定义。
/**
* 创建JWT签名
*
* @param userId
* @return
* @throws Exception
*/
public static String createJWT(String userId) throws Exception {
Long expireTime = 28800000L;
Date expiresDate = new Date(System.currentTimeMillis() + expireTime);
try {
Algorithm algorithm = Algorithm.HMAC256(APP_SECRET);
String token = JWT.create()
.withIssuer(userId)
.withExpiresAt(expiresDate)
.sign(algorithm);
return token;
} catch (JWTCreationException exception) {
logger.error("创建JWT签名JWTCreationException:{}", exception);
throw new Exception("创建JWT签名失败,请稍后重试");
}
}
/**
* 解析JWT分析
*
* @param token
* @return
*/
public static DecodedJWT decodeJWT(String token) throws Exception {
try {
DecodedJWT decode = JWT.decode(token);
return decode;
} catch (JWTDecodeException exception) {
logger.error("解析JWT签名JWTCreationException:{}", exception);
throw new Exception("解析JWT签名失败,请稍后重试");
}
}
/**
* 校验token
* @param token
* @param userId
* @return
* @throws Exception
*/
public static DecodedJWT validateJWT(String token, String userId) throws Exception {
try {
Algorithm algorithm = Algorithm.HMAC256(APP_SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(userId)
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);
return jwt;
} catch (JWTDecodeException exception) {
logger.error("校验JWT签名JWTCreationException:{}", exception);
throw new Exception("校验JWT签名失败,请稍后重试");
}
}