• 介绍 jwt
  • 实践
  • 定义功能
  • 签发接口
  • 验证中间件
  • 使用
  • 总结
  • 当前部分的代码

在典型的业务场景中, 认证与鉴权是十分基础的.

对于 API 接口, 通常是在第一次验证之后生成一个带有时效的 token. 接下来的一系列请求都携带这个 token, 服务器会对这个 token 进行验证.

介绍 jwt

JSON Web Tokens(jwt) 是一种用于在两个主体间传递认证消息的方式. 注意, 消息是通过数字签名的, 因此可以被验证和信任, 但却不是加密的.

一个 jwt 由三部分组成:

  • Header
  • Payload
  • Signature

Header 部分通常只有两个字段, 分别定义了签名算法和 token 类型.

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

Payload 部分是实际负载, 用于声明. 通常存储一些用户 ID 之类的索引数据, 也可以放一些其他有用的信息. 注意, 不要存储机密数据.

jwt 规范也在 Payload 中预定义了推荐字段, 但非强制的, 但很多库都会遵照着实现. 比如 iss 字段定义发布者, exp 定义 token 的过期时间. 更多字段可以在 rfc7519 规范 中查看.

Signature 就是签名了, 大致样式如下:

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

将 header 和 payload 分别使用 base64UrlEncode 编码, 中间加上点号., 然后使用 header 中指定的签名算法.

签名用于发布者验证消息没有被篡改, 如果使用非对称加密, 还可以验证发布者身份.

jwt 通常用在请求头的 Authorization 字段中, 形如:

Authorization: Bearer <token>

更多内容可以参考 Introduction to JSON Web Tokens.

实践

对于如何使用 jwt, 应该是非常清晰了. 首先, 我们要定义一个接口签发 jwt. 获取到 token 之后, 就可以在请求其他资源时带上这个 token.

验证环节可以用到上一节中讲到的中间件技术.

jwt.io 页面上列出了很多 Go 库, 这里选择功能最全的 github.com/gbrlsnchs/jwt/v3.

go get -u github.com/gbrlsnchs/jwt/v3

定义功能

对于 jwt 有两个必须实现的功能, 签发 token 和验证 token.

首先, 首先定义 Payload 内容, 这里保持用户的 ID 和昵称.

// 记录登录信息的 JWT
type LoginToken struct {jwt.PayloadID       uint   `json:"id"`Username string `json:"username"`
}

然后选择签名方法.

// 签名算法, 随机, 不保存密钥, 每次都是随机的
var privateKey, _ = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
var publicKey = &privateKey.PublicKey
var hs = jwt.NewES256(jwt.ECDSAPublicKey(publicKey),jwt.ECDSAPrivateKey(privateKey),
)

编写签发和验证函数.

// 签名
func Sign(id uint, username string) (string, error) {now := time.Now()pl := LoginToken{Payload: jwt.Payload{Issuer:         "coolcat",Subject:        "login",Audience:       jwt.Audience{},ExpirationTime: jwt.NumericDate(now.Add(7 * 24 * time.Hour)),NotBefore:      jwt.NumericDate(now.Add(30 * time.Minute)),IssuedAt:       jwt.NumericDate(now),JWTID:          uuid.NewV4().String(),},ID:       id,Username: username,}token, err := jwt.Sign(pl, hs)return string(token), err
}// 验证
func Verify(token []byte) (*LoginToken, error) {pl := &LoginToken{}_, err := jwt.Verify(token, hs, pl)return pl, err
}

签发接口

首先, 构建一个接口签发 jwt.

func Login(ctx *gin.Context) {var u model.UserModel// 应该使用 ShouldBindJSON, 以便使用自定义的 handler.SendResponseif err := ctx.ShouldBindJSON(&u); err != nil {handler.SendResponse(ctx, errno.New(errno.ErrBind, err), nil)return}user, err := model.GetUserByName(u.Username)if err != nil {handler.SendResponse(ctx, errno.New(errno.ErrDatabase, err), nil)return}if err := user.Compare(u.Password); err != nil {handler.SendResponse(ctx, errno.New(errno.ErrPasswordIncorrect, err), nil)return}// 签发 tokent, err := token.Sign(user.ID, user.Username)if err != nil {handler.SendResponse(ctx, errno.New(errno.ErrTokenSign, err), nil)return}handler.SendResponse(ctx, nil, model.Token{Token: t})
}

用户传递用户名和密码, 通过验证后返回 jwt.

验证中间件

因为验证可能有很多接口都用得到, 所以写成中间件是最自然的方式.

前面介绍过标准的传递 jwt 的方式是存储在 Authorization 请求头中,

Authorization: Bearer <token>

所以, 这里也依据这种规范来验证 jwt.

// AuthJWT 验证 JWT 的中间件
func AuthJWT() gin.HandlerFunc {return func(ctx *gin.Context) {header := ctx.GetHeader("Authorization")headerList := strings.Split(header, " ")if len(headerList) != 2 {err := errors.New("无法解析 Authorization 字段")handler.SendResponse(ctx, errno.New(errno.ErrTokenInvalid, err), nil)ctx.Abort()return}t := headerList[0]content := headerList[1]if t != "Bearer" {err := errors.New("认证类型错误, 当前只支持 Bearer")handler.SendResponse(ctx, errno.New(errno.ErrTokenInvalid, err), nil)ctx.Abort()return}if _, err := token.Verify([]byte(content)); err != nil {handler.SendResponse(ctx, errno.New(errno.ErrTokenInvalid, err), nil)ctx.Abort()return}ctx.Next()}
}

使用

定义好中间件后, 就可以在 router 中使用了.

g.POST("/v1/create", user.Create) // 为了方便创建用户, 无需认证u := g.Group("/v1/user")
u.Use(middleware.AuthJWT()) // 添加认证
{u.GET("", user.List)u.POST("", user.Create)u.GET("/:id", user.Get)u.PUT("/:id", user.Save)u.PATCH("/:id", user.Update)u.DELETE("/:id", user.Delete)
}

这里为了方便, 有个创建用户的接口放在了外边, 逃避了 jwt 验证. 不然一开始没有用户又无法创建挺尴尬的.

总结

认证与鉴权是 API 接口必不可少的一部分, 这里介绍了 jwt. 更复杂强大的授权协议是 OAuth 2.0, OAuth 2.0 更多用在协作共享资源上, 对于简单的 API 服务器, jwt 就足够了. jwt 也可以作为 OAuth 2.0 的一部分, 用于承载内容.

当前部分的代码

作为版本 v0.9.0

使用 做签名的post_使用 Go 添加 JWT 认证相关推荐

  1. 使用 做签名的post_腾讯IMWeb团队是如何使用 NodeJS 实现 JWT 原理

    jwt是json web token的简称,本文介绍它的原理,最后后端用nodejs自己实现如何为客户端生成令牌token和校验token 作者:腾讯IMWeb团队.https://juejin.im ...

  2. 使用 做签名的post_基础实操|使用jmeter对聊天软件进行接口测试

    前言 准备上架一款聊天app,上架之前准备做一些测试工作,模拟用户进入房间,维持心跳,房间送礼,发言等行为(因为用的第三方im以及声网,这些都是基于http的),也不是很懂测试,听老大说过一嘴,可以用 ...

  3. 超级签名与企业签名有什么区别,开发者想要做签名分发需要注意什么?怎么防止入坑(当然入坑是必须的)

    痛苦的宝贝们分享一下分发过程做签名的注意事项!满满的都是智商在飞驰 跑路!跑路!跑路!我跑你*呀你!为啥不能好好沟通呢?是早就想好了这样还是真的没有办法?那么肯定就是有办法不给解决!其实细细算一笔账单 ...

  4. PyQT5一起学做图书管理系统(6)添加/删除书籍

    PyQT5一起学做图书管理系统(6)添加/删除书籍 环境 系统:windows10系统 编辑器:Sublime3 编程语言:python3+pyqt5 前言 本节来实现书籍的添加与删除,还是那句话,记 ...

  5. 15个可以做签名的高权重论坛

    经过了这么长时间的Seo学习和探索,结合自己博客分享的实践,收集了一些做签名的高权重论坛,一共15个论坛.我想做seo的朋友都希望扩大网站 的领域范围,当然也不会出错过论坛签名这个机会了,这些论坛,只 ...

  6. 炫界 (667) -(回应骑两小)_适合做签名的文艺小句子 适合做签名的文艺小句

    适合做签名的文艺小句子 适合做签名的文艺小句 发布时间:2020-11-08 19:32 编辑:小云 点击: 次 1.撒娇是察觉到了被偏爱的可能. 2.若能避开猛烈的狂喜 自然不会有悲痛来袭. 3.温 ...

  7. android http协议添加Authorization认证方式

      今天,简单讲讲android里如何使用http请求时在头部添加Authorization认证方式. 其实也很简单,之前需要做一个功能,在android去使用http访问设备,但是每次的访问 ...

  8. 关于wifi portal认证--为浏览器添加wifi认证功能

    ###关于wifi portal认证–为浏览器添加wifi认证功能 1.什么是portal认证 2.android的原生portal认证概要讲述 3.独立出portal认证到浏览器 ####1.什么是 ...

  9. 给WordPress添加SSL认证(HTTPS)

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...

  10. newifi3 web认证_关于wifi portal认证--为浏览器添加wifi认证功能

    关于wifi portal认证--为浏览器添加wifi认证功能 1.什么是portal认证 2.android的原生portal认证概要讲述 3.独立出portal认证到浏览器 1.什么是portal ...

最新文章

  1. CQRS体系结构模式实践案例:Tiny Library:领域仓储与事件存储
  2. 【机器学习】算法模型自动超参数优化方法
  3. ejb3.0 中数据库的配置
  4. flume介绍及应用
  5. Mad Libs游戏:熟悉python编程环境,基本输入输出
  6. css文字上浮div,css文字样式与div
  7. desc和asc用法
  8. 导航上显示某个地点已关闭什么意思_大众MIB(275)教程之导航使用
  9. Oracle导入sas数据集,来自SAS数据集的Oracle表
  10. 【BZOJ 3097】 Hash Killer I
  11. ios QQ下拉列表 UITableViewHeaderFooterView
  12. linux 模拟误码率,基于System View的比特误码率测试的仿真研究
  13. Matlab求集合交集和并集
  14. 配置opencv,丢失 opencv_world300d.dll
  15. python列表两两组合_关于python:两个列表之间的组合?
  16. oracle表如何做统计分析,Oracle表统计信息的分析
  17. 前端简历如何描述项目经历
  18. cube escape语言设置_Cube Escape Harvey's Box攻略
  19. 谨慎处理 Service Worker 的更新
  20. SAP 标准带料委外加工 投A产B业务场景及功能操作演示(1)

热门文章

  1. 有关table的几个问题
  2. makefile的编写(4)
  3. 解决精简版的XP下,无法使用运程桌面
  4. 基于HTTP协议的轻量级开源简单消息队列服务:HTTPSQS
  5. matlab 函数整理(资料备份儿)
  6. 「中间件」消息中间件如何实现每秒几十万的高并发写入?
  7. pycharm的编码问题
  8. 正则匹配字符串无匹配不到_10. 正则表达式匹配
  9. PHPStorm 设置背景图片
  10. easyui输入框模糊查询