http://blog.csdn.net/wangshubo1989/article/details/74529333

之前写过关于golang中如何使用cookie的博客: 
实战–go中使用cookie

今天就来跟大家简单介绍一下golang中如何使用token,当然是要依赖一下github上的优秀的开源库了。

首先,要搞明白一个问题,token、cookie、session的区别。

token、cookie、session的区别

Cookie 
Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie。

内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。硬盘Cookie保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的。所以,按存在时间,可分为非持久Cookie和持久Cookie。

cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。

cookie由服务器生成,发送给浏览器,浏览器把cookie以key-value形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

Session

session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。

session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。

服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

Token 
token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库

这里的token是指SON Web Token: 
JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).

使用JWT进行认证 
JSON Web Tokens (JWT) are a more modern approach to authentication.

As the web moves to a greater separation between the client and server, JWT provides a wonderful alternative to traditional cookie based authentication models.

JWTs provide a way for clients to authenticate every request without having to maintain a session or repeatedly pass login credentials to the server.

用户注册之后, 服务器生成一个 JWT token返回给浏览器, 浏览器向服务器请求数据时将 JWT token 发给服务器, 服务器用 signature 中定义的方式解码 
JWT 获取用户信息.

一个 JWT token包含3部分: 
1. header: 告诉我们使用的算法和 token 类型 
2. Payload: 必须使用 sub key 来指定用户 ID, 还可以包括其他信息比如 email, username 等. 
3. Signature: 用来保证 JWT 的真实性. 可以使用不同算法 

JWT应用

上面说了那么多,接下来就是要coding了。 
用到的开源库: 
github.com/codegangsta/negroni 
Idiomatic HTTP Middleware for Golang 
http的一个中间件

github.com/dgrijalva/jwt-go 
Golang implementation of JSON Web Tokens (JWT)

github.com/dgrijalva/jwt-go/request

这里分两个api,一个是通过login获取token,然后根据token访问另一个api。首先看看login是如何生成token的: 
当然首先是验证用户名和密码,为了节省篇幅这里只是代码片段,完整代码最后献上。

    token := jwt.New(jwt.SigningMethodHS256)
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Add(time.Hour * time.Duration(1)).Unix()
claims["iat"] = time.Now().Unix()
token.Claims = claims if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Error extracting the key")
fatal(err)
} tokenString, err := token.SignedString([]byte(SecretKey))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Error while signing the token")
fatal(err)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

接下来就是验证token的中间件了:

    token, err := request.ParseFromRequest(r, request.AuthorizationHeaderExtractor,
func(token *jwt.Token) (interface{}, error) {
return []byte(SecretKey), nil
}) if err == nil {
if token.Valid {
next(w, r)
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Token is not valid")
}
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Unauthorized access to this resource")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

最后完整代码:

package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"time" "github.com/codegangsta/negroni"
"github.com/dgrijalva/jwt-go"
"github.com/dgrijalva/jwt-go/request"
) const (
SecretKey = "welcome to wangshubo's blog"
) func fatal(err error) {
if err != nil {
log.Fatal(err)
}
} type UserCredentials struct {
Username string `json:"username"`
Password string `json:"password"`
} type User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
Password string `json:"password"`
} type Response struct {
Data string `json:"data"`
} type Token struct {
Token string `json:"token"`
} func StartServer() { http.HandleFunc("/login", LoginHandler) http.Handle("/resource", negroni.New(
negroni.HandlerFunc(ValidateTokenMiddleware),
negroni.Wrap(http.HandlerFunc(ProtectedHandler)),
)) log.Println("Now listening...")
http.ListenAndServe(":8080", nil)
} func main() {
StartServer()
} func ProtectedHandler(w http.ResponseWriter, r *http.Request) { response := Response{"Gained access to protected resource"}
JsonResponse(response, w) } func LoginHandler(w http.ResponseWriter, r *http.Request) { var user UserCredentials err := json.NewDecoder(r.Body).Decode(&user) if err != nil {
w.WriteHeader(http.StatusForbidden)
fmt.Fprint(w, "Error in request")
return
} if strings.ToLower(user.Username) != "someone" {
if user.Password != "p@ssword" {
w.WriteHeader(http.StatusForbidden)
fmt.Println("Error logging in")
fmt.Fprint(w, "Invalid credentials")
return
}
} token := jwt.New(jwt.SigningMethodHS256)
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Add(time.Hour * time.Duration(1)).Unix()
claims["iat"] = time.Now().Unix()
token.Claims = claims if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Error extracting the key")
fatal(err)
} tokenString, err := token.SignedString([]byte(SecretKey))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Error while signing the token")
fatal(err)
} response := Token{tokenString}
JsonResponse(response, w) } func ValidateTokenMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { token, err := request.ParseFromRequest(r, request.AuthorizationHeaderExtractor,
func(token *jwt.Token) (interface{}, error) {
return []byte(SecretKey), nil
}) if err == nil {
if token.Valid {
next(w, r)
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Token is not valid")
}
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Unauthorized access to this resource")
} } func JsonResponse(response interface{}, w http.ResponseWriter) { json, err := json.Marshal(response)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write(json)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147

通过postman进行验证: 
login: 

根据获得token进行get请求: 

Go实战--golang中使用JWT(JSON Web Token)的更多相关文章

  1. 如何在SpringBoot中集成JWT(JSON Web Token)鉴权

    这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...

  2. 什么是JWT(Json Web Token)

    什么是 JWT (Json Web Token) 用户认证是计算机安全领域一个永恒的热点话题. JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该to ...

  3. Java JWT: JSON Web Token

    Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...

  4. JWT(JSON Web Token) 【转载】

    JWT(JSON Web Token) 什么叫JWTJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. 一般来说,互联网用户认证是这样子的. 1.用户向服务器发送用户名和密码. ...

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

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

  6. 关于JWT(Json Web Token)的思考及使用心得

    什么是JWT? JWT(Json Web Token)是一个开放的数据交换验证标准rfc7519(php 后端实现JWT认证方法一般用来做轻量级的API鉴权.由于许多API接口设计是遵循无状态的(比如 ...

  7. API安全验证之JWT(JSON WEB TOKEN) OLCMS

    假如www.olcms.com/getUserInfo获取用户信息,你怎么知道当前用户是谁?有人说登陆时候我把他UID写入session了,如果是API接口,没有session怎么办,那么就需要把UI ...

  8. 5分钟搞懂:JWT(Json Web Token)

    https://www.qikegu.com/easy-understanding/892 JWT 基于token的用户认证原理:让用户输入账号和密码,认证通过后获得一个token(令牌),在toke ...

  9. 温故知新,.Net Core遇见JWT(JSON Web Token)授权机制方案

    什么是JWT JWT (JSON Web Token) 是一个开放标准,它定义了一种以紧凑和自包含的方法,用于在双方之间安全地传输编码为JSON对象的信息. 因此,简单来说,它是JSON格式的加密字符 ...

随机推荐

  1. java 浅拷贝和深拷贝 对象克隆clone

    分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...

  2. Windows 下面 redis 发布为服务的官方方法

    除了 NSSM 之外 另外一种方式 感觉还是很好用的 redis-server --service-install redis.windows.conf --loglevel verbose 感觉也可 ...

  3. CentOs7安装docker(第二篇)

    一.Docker的概念: Docker: 镜像:Images 类似于面向对象中的类 容器:Container 类似于面向对象中的对象 它们之间的关系:容器Container通过镜像Images来创建 ...

  4. Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-

    Maven项目报错:Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clea ...

  5. mysql修改默认端口号后从windows命令行登录

    mysql -u root -p -P 大写的P代表端口号,小写的p代表密码

  6. Golang的channel使用以及并发同步技巧

    在学习<The Go Programming Language>第八章并发单元的时候还是遭遇了不少问题,和值得总结思考和记录的地方. 做一个类似于unix du命令的工具.但是阉割了一些功 ...

  7. kdump简单的介绍

    kdump是2.6.16之后,内核引入的一种新的内核崩溃现场信息收集工具.当一个内核崩溃后(我们称之为panic),内核会使用kexec(类似于进程的exec,把当前内核换掉)进入到一个干净的备份内核 ...

  8. Alertmanager 安装(k8s报警)

    一.下载Alertmanager https://prometheus.io/download/ wget https://github.com/prometheus/alertmanager/rel ...

  9. HTTP协议 - 使用php模拟get/post请求

    首先 有个疑问, 是不是只有浏览器才能发送http 请求? 答案肯定是错的,第一篇就说了,http是由请求行,请求头,请求主体三个部分组成,那么我们可不可以用代码来模拟一下get和post请求呢: 首 ...

  10. rmse均方根误差

    rmse=sqrt(sum((w-r).^2)/length(w))