Json Web Token (JWT),是一个非常轻巧的规范,这个规范允许在网络应用环境间客户端和服务器间较安全的传递信息。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。

在web应用中,我们提供的API接口,通过GET或者POST方式调用,在调用过程中,就存在着接口认证及数据的安全性问题。例如如下问题:

1、请求来自哪里,身份是否合法?

2、请求参数是否被篡改?

3、客户端请求的唯一性,是否为重复请求攻击(RepeatAttack)?

传统的Session认证方式

在传统的web应用中,服务端成功相应请求者,返回正常的response依赖于服务端通过一种存储机制把每个用户经过认证之后的会话信息(session)记录服务器端,一般记录到内存、磁盘、数据库中,这种方式在请求量和用户量增多的时候无疑会增大服务端的开销;如果是记录在内存中,那每次请求都分发登到该机器上才能授权获取资源,那在分布式系统中就存在着问题;因为是基于Cookie的,如果Cookie被截获,攻击者会盗用身份信息进行发送恶意请求,也就是“跨站请求伪造”(CSRF)。

基于token的认证方式

客户端用用户名和密码经过服务器认证之后,服务器会签发一个token返回给客户端,客户端存储token(一般存在请求头里),并且在之后的请求里附带此token,服务器每次会解签名token,验证通过则返回资源。另外服务端要支持CORS跨来源资源共享)策略,服务器处理完请求之后,会再返回结果中加上Access-Control-Allow-Origin。

jwt的生成

token是接口的令牌,好比去衙门办事,“衙门口朝南开,有理无钱莫进来”。没有令牌就别想办事。token的验证方法很多,也生成了很多标准,jwt就是一种基于json的RFC 7519。该标准由三部分组成:

  • header

  • payload

  • signature

header和payload经过base64编码后用点拼接起来。signature是把header和payload编码和拼接后经过加密算法加密,加密时还要一个密码,这个密码保存在服务器端。大致示意图如下:

Header:

head由两部分组成,一个是token类型,一个是使用的算法,如下类型为jwt,使用的算法是HS256。当然,还有HS384、HS512算法。

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

将以上json进行base64编码,当然编码前将json去格式化,如图:

生成的编码为:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

用go语言实现:

package main

import (
"fmt"
"encoding/base64"
) func main() { head1 := `{"typ":"JWT","alg":"HS256"}` fmt.Println(base64.StdEncoding.EncodeToString([]byte(head1)))
}

Payload:

payload 里面是 token 的具体内容,这些内容里面有一些是标准字段,我们也可以添加自定义内容。如下:

{
"iss": "smallsoup",
"iat": 1528902195,
"exp": 1528988638,
"aud": "www.smallsoup.com",
"sub": "smallsoup@qq.com",
"userId": "0418"
}

这里面的前五个字段都是由JWT的标准所定义的,在jwt标准中都可以找到。

  • iss: 该JWT的签发者

  • sub: 该JWT所面向的用户

  • aud: 接收该JWT的一方

  • exp(expires): 什么时候过期,这里是一个Unix时间戳

  • iat(issued at): 在什么时候签发的

最后一个userId表示了用户信息,为自定义字段,我们也可以定义角色等其他字段。以上的json去格式化后的base64编码如下:

eyJpc3MiOiJzbWFsbHNvdXAiLCJpYXQiOjE1Mjg5MDIxOTUsImV4cCI6MTUyODk4ODYzOCwiYXVkIjoid3d3LnNtYWxsc291cC5jb20iLCJzdWIiOiJzbWFsbHNvdXBAcXEuY29tIiwidXNlcklkIjoiMDQxOCJ9

Signature:

JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。

  • header

  • payload

  • secret

假设这里secret为mysecret,则用go语言实现代码如下:

package main

import (
"fmt"
"encoding/base64"
"crypto/hmac"
"crypto/sha256"
"strings"
) func main() { head1 := `{"typ":"JWT","alg":"HS256"}` head1Base64 := base64.StdEncoding.EncodeToString([]byte(head1)) payload1 := `{"iss":"smallsoup","iat":1528902195,"exp":1528988638,"aud":"www.smallsoup.com","sub":"smallsoup@qq.com","userId":"0418"}` payload1Base64 := base64.StdEncoding.EncodeToString([]byte(payload1)) encodedstring := head1Base64 + "." + payload1Base64 hash := hmac.New(sha256.New, []byte("mysecret"))
hash.Write([]byte(encodedstring)) signature := strings.TrimRight(base64.URLEncoding.EncodeToString(hash.Sum(nil)), "=") fmt.Printf(signature)
}

运行结果为:

fjjbA93FTcE71hz_cyIzCUFYdTdyl9hA0w7Pa0ltduc

最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzbWFsbHNvdXAiLCJpYXQiOjE1Mjg5MDIxOTUsImV4cCI6MTUyODk4ODYzOCwiYXVkIjoid3d3LnNtYWxsc291cC5jb20iLCJzdWIiOiJzbWFsbHNvdXBAcXEuY29tIiwidXNlcklkIjoiMDQxOCJ9.fjjbA93FTcE71hz_cyIzCUFYdTdyl9hA0w7Pa0ltduc

实际上https://jwt.io/这个网站提供了这个能力,以及各种语言的生成token和解密token的库。

go语言生成token和解析token:

下面是go语言版的生成token和解析token的案例:

package main

import (
"github.com/dgrijalva/jwt-go"
"fmt"
) func main() { hmacSampleSecret := []byte("mysecret") // Create a new token object, specifying signing method and the claims
// you would like it to contain.
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"iss": "smallsoup",
"iat": 1528902195,
"exp": 1528988638,
"aud": "www.smallsoup.com",
"sub": "smallsoup@qq.com",
"userId": "0418",
}) // Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString(hmacSampleSecret) fmt.Println(tokenString, err) token, err = jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
} // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
return hmacSampleSecret, nil
}) if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
fmt.Println(claims)
} else {
fmt.Println(err)
}
}

具体可以了解github上以下代码的实现。

go get github.com/dgrijalva/jwt-go


本公众号免费提供csdn下载服务,海量IT学习资源,如果你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程IT相关资源。


扫码关注,精彩内容第一时间推给你

浅谈json web token及应用的更多相关文章

  1. 什么是JWT(JSON WEB TOKEN)

    转自于:http://www.jianshu.com/p/576dbf44b2ae 什么是JWT Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准( ...

  2. JWT(Json web token)简介

    Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(S ...

  3. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  4. ( 转 ) 什么是 JWT -- JSON WEB TOKEN

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...

  5. 使用Json Web Token设计Passport系统

    >>Token Auth机制 基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中. 相比原始的Cookie+Session方式,更适合分布式系统的用户认证,绕 ...

  6. 浅谈大型web系统架构

    动态应用,是相对于网站静态内容而言,是指以c/c++.php.Java.perl..net等服务器端语言开发的网络应用软件,比如论坛.网络相册.交友.BLOG等常见应用.动态应用系统通常与数据库系统. ...

  7. JWT【JSON Web Token】 简述

    draft: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html http://tools.ietf.org/html/ ...

  8. 八幅漫画理解使用JSON Web Token设计单点登录系统

    用jwt这种token的验证方式,是不是必须用https协议保证token不被其他人拦截? 是的.因为其实只是Base64编码而已,所以很容易就被解码了.如果你的JWT被嗅探到,那么别人就可以相应地解 ...

  9. JSON Web Token - 在Web应用间安全地传递信息(zhuan)

    来自 http://blog.leapoahead.com/2015/09/06/understanding-jwt/ JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用 ...

随机推荐

  1. JavaScript数组和伪数组

    伪数组和数组 记住一句话: 伪数组是一个Object,数组是Array. 对象和数组之间的关系 JavaScript的内置函数继承与 Object.prototype. 可以认为new Array() ...

  2. elementUI树状图竖向滚动条和横向滚动条问题

    添加样式: <div class="device-tree"> <el-scrollbar style="height:100%"> & ...

  3. 快速了解TCP的流量控制与拥塞控制

    有关TCP你不能不知道的三次握手和四次挥手问题,点我跳转 流量控制 1. 滑动窗口 数据的传送过程中很可能出现接收方来不及接收的情况,这时就需要对发送方进行控制以免数据丢失.利用滑动窗口机制可以很方便 ...

  4. FreeSql (二十六)贪婪加载 Include、IncludeMany、Dto、ToList

    贪婪加载顾名思议就是把所有要加载的东西一次性读取. 本节内容为了配合[延时加载]而诞生,贪婪加载和他本该在一起介绍,开发项目的过程中应该双管齐下,才能写出高质量的程序. Dto 映射查询 Select ...

  5. Qt 纯属娱乐-模拟一个导航定位系统

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/115397 ...

  6. 【教程】Bluestacks0.7.9.860以上版3分钟教你摇一摇

    Bluestacks 0.7.9.860 版或以上 , 打开文件夹Win 7 用户 : C:\ProgramData\Bluestacks\UserData\InputMapperWin XP 用户 ...

  7. charles SSL代理设置

    本文参考:charles SSL代理设置 charles SSL代理设置 SSL Proxying Srtting 这里最常用的设置就是第一个ssl proxying,这里记录了需要捕获哪些ssl的信 ...

  8. Docker学习之volume

    提供独立于容器之外的持久化存储 容器中的数据会随着容器的消失而消失,为了解决这个问题,产生了数据卷volume. 例子,比如说mysql容器,msyql中的数据应该是持久化的,故应该存储在volume ...

  9. JAVA数据处理的常用技术

    背景 在实际开发中,数据的处理有五种:获取.传输.存储.分析.转换.每种各对应一些常用的技术. 序列化和反序列化 序列化是将对象的信息转换为可传输或可存储形式的过程.反序列化就是反过来让这些可传输的. ...

  10. [Leetcode] 第148题 排序链表

    一.题目描述 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示 ...