在吗?认识一下JWT(JSON Web Token) ?

什么是JSON Web Token

官网介绍:html

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地将信息做为JSON对象传输。因为此信息是通过数字签名的,所以能够被验证和信任。可使用秘密(使用HMAC算法)或使用RSAECDSA的公用/专用密钥对对JWT进行签名前端

尽管能够对JWT进行加密以在各方之间提供保密性,但咱们将重点关注已签名的令牌。签名的令牌能够验证其中包含的声明的完整性,而加密的令牌则将这些声明隐藏在其余方的面前。当使用公钥/私钥对对令牌进行签名时,签名还证实只有持有私钥的一方才是对其进行签名的一方。python

emmmm.......balabala一堆文字,那么咱们来简单总结下:web

JWT是一个JSON信息传输的开放标准,它可使用密钥对信息进行数字签名,以确保信息是可验证和可信任的。算法

JWT的结构是什么?

JWT由三部分构成:header(头部)、payload(载荷)和signature(签名)。 以紧凑的形式由这三部分组成,由“.“分隔。json

所以,JWT一般以下所示。后端

xxxxx.yyyyy.zzzzzapi

让咱们把这串奇奇怪怪的东西分解开来:安全

header并发

header一般由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA等等。

例如:

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

显而易见,这货是一个json数据,而后这货会被Base64编码造成JWT的第一部分,也就是xxxxx.yyyyy.zzzzz中的xxxxxx

Payload

这货是JWT的第二部分,叫载荷(负载),内容也是一个json对象,它是存放有效信息的地方,它能够存放JWT提供的现成字段 :

  • iss: 该JWT的签发者。

  • sub: 该JWT所面向的用户。

  • aud: 接收该JWT的一方。

  • exp(expires): 何时过时,这里是一个Unix时间戳。

  • iat(issued at): 在何时签发的。

举个例子:

{   "iss": "www.baidu.com",
  "sub": "you",   "aud": "me",
  "name": "456",
  "admin": true,   "iat": 1584091337,   "exp": 1784091337,
}

这货一样会被Base64编码,而后造成JWT的第二部分,也就是xxxxx.yyyyy.zzzzz中的yyyyyy

Signature

这是JWT的第三部分,叫作签名,此部分用于防止JWT内容被篡改。将上面的两个编码后的字符串都用英文句号.链接在一块儿(头部在前),就造成了

xxxxxx.yyyyyy

而后再使用header中声明签名算法进行签名。 若是要使用HMAC SHA256算法,则将经过如下方式建立签名:

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

固然,在加密的时候,咱们还须要提供一个密钥(secret),咱们能够本身随意指定。这样就造成了JWT的第三部分,也就是xxxxx.yyyyy.zzzzz中的zzzzzz

最后,咱们把这三个部分拼在一块儿,就造成了一个完整的JWT。

下面展现了一个完整的JWT,它先对header和payload进行编码,最后用一个密钥造成了签名。

若是咱们想试验一下的话,能够在JWT的官网进行debugger。贴一下官网: https://jwt.io/

JSON Web Token认证流程

何时应该使用JSON Web Token?

如下是JSON Web Token 有用的一些状况:

  • 受权:这是使用JWT的最多见方案。一旦用户登陆,每一个后续请求将包括JWT,从而容许用户访问该令牌容许的路由,服务和资源。单一登陆是当今普遍使用JWT的一项功能,由于它的开销很小而且能够在不一样的域中轻松使用。

  • 信息交换:JSON Web Token是在各方之间安全地传输信息的好方法。由于能够对JWT进行签名(例如,使用公钥/私钥对),因此您能够肯定发件人是他们所说的人。此外,因为签名是使用标头和有效负载计算的,所以您还能够验证内容是否遭到篡改。

那么,有人就会说了,道理我都懂,我应该怎样去实现呢?莫慌。。 

现?

接下来我会用python实现JWT,不想拉仇恨,可是,python大法好啊。。。。

在先后端分离的项目中,咱们须要与前端约定一种身份认证机制。当用户登陆的时候,后端会生成token,而后返回给前端,前端须要将token拿到并按照必定规则放到header中,在下一次请求的时候一并发送给后端,后端进行token身份校验。

这里咱们约定前端请求后端服务时须要添加头信息Authorization ,内容为token。

我用的是fastapi web框架,搭建项目很是快。

from datetime import timedelta, datetime

import jwt
from fastapi import FastAPI, HTTPException, Depends
from starlette.status import HTTP_401_UNAUTHORIZED
from starlette.requests import Request
app = FastAPI()

SECRET_KEY = "sdifhgsiasfjaofhslio" # JWY签名所使用的密钥,是私密的,只在服务端保存
ALGORITHM = "HS256" # 加密算法,我这里使用的是HS256
@app.get("/")
async def root():
    return {"message": "Hello World"}

@app.post("/create_token")
def create_token(username,password):
    if username == "123" and password == "123":
        access_token_expires = timedelta(minutes=60)
        expire = datetime.utcnow() + access_token_expires

        payload = {
                    "sub": username,
                    "exp": expire
                     }
        # 生成Token,返回给前端
        access_token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
        return {"access_token": access_token, "token_type": "bearer"}

    else:
        raise HTTPException(
            status_code=HTTP_401_UNAUTHORIZED,
            detail="username or password are not true",
            headers={"WWW-Authenticate": "Bearer"}
        )


def authorized_user(token):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        print(username)
        if username == "123":
            return username
    except jwt.PyJWTError:
        raise HTTPException(
        status_code=HTTP_401_UNAUTHORIZED,
        detail="认证失败,无权查看",
        headers={"WWW-Authenticate": "Bearer"},)



@app.get("/app")
def create_token(request: Request):
    print(request.headers.get("host"), request.headers.get("Authorization"))
    user = authorized_user(request.headers.get("Authorization")) # 验证Token
    if user:
        return {"username": user,"detail": "JWT经过,查询成功"}

这里,因为现有的JWT库已经帮咱们封装好了,咱们可使用JWT直接生成 token,不用手动base64加密和拼接。

测试一下:

启动项目以后,咱们打开http://127.0.0.1:8000/docs# ,就会看到如下咱们编写好的api:

首先,咱们先验证一下create_token接口

当咱们输入用户名,密码后,后端进行验证,验证成功后会返回给前端一个token,也就是JWT。当前端拿到这个token以后,下次在请求的时候就必需要带上这个token了,由于先后端已经约定好了。接下来咱们试一下:

认证失败???

什么缘由致使的呢??让咱们点开检查抓一下包看看:

恍然大悟,刚才咱们说过,先后端事先约定好的,请求的header中必定要带上token,在Authorization ,内容token。咱们如今这个请求的header中并无带上token,那这种debug模式下又是改不了请求header信息的,咱们可使用接口测试工具进行测试,我主推Postman!!!,让咱们来试一下:

至此,JWT介绍以及使用梳理完毕。

最后,感谢女友在生活中,工做上的包容、理解与支持 !

相关文章
相关标签/搜索