登录鉴权:JWT(json web token)实现认证

引言

应用场景:

  • 登录授权:它相比原先的session、cookie来说,更快更安全,跨域也不再是问题
  • 传递数据

Base64URL算法

在讲解JWT的组成结构前,我们先来讲解一下Base64URL算法,这个算法和Base64算法类似,,但是有一点区别。

我们通过名字可以得知这个算法使用于URL的,因此它将Base64中的+,/,=三个字符替换成了-,_,删掉了=。因为这

三个字符在URL中有特殊含义。

 

JWT介绍

JWT是JSON Web Token的缩写,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519)。
JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和
Token生成过程,特别适用于分布式站点的单点登录(SSO)场景。

一个JWT Token格式如下:

 

他是由.分割的三部分组成,这三部分依次是: 

  • 头部(Header)
  • 负载(Payload)
  • 签名(Signature)

头部和负载以json形式存在,这就是JWT这种的JSON,三部分的内容都分别单独经过了Base64编码,以

. 拼接成一个JWT Token。

 

 JWT优缺点

JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用

cookie的浏览器环境中正常有运行。

JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储Sesssion所需要

引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存在Token中,JWT token一旦

签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到了。

预备知识

关键字去空格处理

public class PageQuery{
  private String keyword;
  
  public String getKeyword(){
    return (keyword+"").trim();
    return StringUtils.isBlank(keyword)?keyword:keyword.trim();
  } }

 

JWT认证流程

 

 JWT不是一个具体的技术实现,而更像是一种标准,JWT规定了数据传输的结构,一串完整的JWT由三段落组成,

每个段落用英文句号连接(.)连接, 他们分别是:Header、Payload、Signature,所以,常规的JWT内容格式是这样的:

Header.Payload.Signature。并且这一串内容会进行加密,解码就可以看到实际传输的内容。

  • Header:加密方式、type
{
"type":"jwt",
"alg":"HS26"
}
  • Payload:实际传递的参数内容,推荐对payload内容进行加密。
  • Signature: 签名,用于判断Header、Payload有没有被人篡改;如果被篡改,那么这条JWT将会被视为无效。

内容前面的"Bearer"是固定的,并且还得多加一个空格做分割。

 

 

token组成

生成jwt:sign(Header+Payload+Signature+expiresAt)

return create(header,cllaims,JWT_ISSUER,TOKEN_TIMEOUT);

 

头部(Header)

JWT的Header中存储了所使用的加密算法和Token类型。

{

"typ":"JWT",
"alg":"HS256"
}

Payload有效载荷

也是一个json对象,JWT规定了7个官方字段供选用

1 iss (issuer) : 签发人
2 exp (expiration time) : 过期时间
3 sub (subject) : 主题
4 aud (audience) : 受众
5 nbf (Not Before) : 生效时间
6 iat (Issued At) : 签发时间
7 jti (JWT ID) : 编号

除了官方字段,开发者也可以自己指定字段和内容。

JWT默认是不加密的,任何人都可以读到,所以不要把重要信息放到这里。

有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息

{
    "iss":"ios逆向",
    "exp":1638841050,
    "iat":1638840690,
    "userId":"1",
    "account":"admin"  
}

 

Signature签名

Signature部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的

签名算法(默认是HMAC SHA256),按照下面的公式产生签名。

HMAXSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

 

将Header和Payload拼接生成一个字符串,使用HS26算法和我们提供的密钥(secret,服务器自己提供的一个字符串)

对str进行加密生成最终的JWT,即我们需要的令牌(token)

代码实现:生成token

生成jwt:sign(Header+Payload+Signature+expiresAt)

Algorithm algorithm = Algorithm.HMAC256(tokenkey);  //使用HS256算法加密
Date date = new Date(System.currentTimeMillis()+timeout);
JWTCreator.Builder builder = JWT.Create()
.withHeader(header);
.withIssuer(issuer)
.withExpiresAt(date)

for(String key: claims.keySet()){
  builder.withClaim(key,claims.get(key))
}
token = builder.sign(algorithm);

 

验证token

网关验证token

使用拦截器验证token

 

posted @ 2022-12-27 12:00  塞纳纽斯  阅读(421)  评论(0)    收藏  举报