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. Maven学习归纳(一)——简单的环境配置入门

    一.Maven的基本概念 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的编译,测试,构建,报告和文档的软件项目管理工具和解决依赖关系的工具. 1.1 项目的构建 项目的构建 ...

  2. ubuntu上vritualbox为系统分配硬盘空间

    VBoxManage是virtualbox 在ubuntu上提供的管理virtualbox的命令行命令 VBoxManage modifyhd windowsDevEnv --resize VBoxM ...

  3. 简单的Socket通信(简单的在线聊天)---winform

    注:本博客适合刚开始学习winform程序的初学者,大牛请绕道(跪求大牛指导文中不足) .....10w字废话自动省略,直接开始正题. 首先从最基本的建立winform开始(本项目用的Vs2017) ...

  4. FJUT2019暑假周赛一题解

    A.排队问题*-* 题意就是有长度为L的序列,每位的取值可以是'f'或者'm',问不包含'fff'和'fmf'的个数. 打表找规律 不难找出递推公式为F[n] = F[n-1] + F[n-3] + ...

  5. TensorFlow2.0(1):基本数据结构—张量

    1 引言 TensorFlow2.0版本已经发布,虽然不是正式版,但预览版都发布了,正式版还会远吗?相比于1.X,2.0版的TensorFlow修改的不是一点半点,这些修改极大的弥补了1.X版本的反人 ...

  6. Spark学习之RDDs介绍

    什么是RDDS? RDDS即Resilient distributed datasets(弹性分布式数据集). Spark中,所有计算都是通过RDDs的创建,转换,操作完成的. 一个RDD是一个不可改 ...

  7. ActiveMQ+ZooKeeper搭建高可用集群

    一.说明 实际的应用中,一般为了应用的高可用性,都会搭建集群环境去处理.部署多台应用,这样,即使一台有问题,其他热备应用可以立马顶上,继续提供服务. ActiveMQ的集群部署,基于zookeeper ...

  8. shiro+spring

    公司自用的管理系统使用了shiro,但是对于这个登录页面跳转.登录的过程逻辑以及登录成功或者失败的跳转页面一直不理解,查看相关文档资料,整理出一些结果并本地调试测试,记录下备以后回顾之用. 对于spr ...

  9. 使用 Fabric 自动化部署 Django 项目

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在上一篇教程中,我们通过手工方式将代码部署到了服务器.整个过程涉及到十几条命令,输了 ...

  10. linux环境下Nginx的安装

    因为工作环境大多数都是windows server服务器,仅有的linux服务器同事们都在抢着用,所以特意买了一台阿里云服务器,感兴趣的小伙伴可以了解一下,一年只要293: https://promo ...