作者:沫小兮 | 来源:互联网 | 2023-09-17 08:23
一。token、cookie、session的区别1。cookieCookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie。内存Cookie
一。token、COOKIE、session的区别
1。COOKIE
COOKIE总是保存在客户端中,按在客户端中的存储位置,可分为内存COOKIE和硬盘COOKIE。
内存COOKIE由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。
硬盘COOKIE保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘COOKIE不会被删除,其存在时间是长期的。
所以,按存在时间,可分为非持久COOKIE和持久COOKIE。
COOKIE 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
COOKIE由服务器生成,发送给浏览器,浏览器把COOKIE以key-value形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该COOKIE发送给服务器。
由于COOKIE是存在客户端上的,所以浏览器加入了一些限制确保COOKIE不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的COOKIE数量是有限的。
2。session
session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。
session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,
然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,
可以有很多种方式,对于浏览器客户端,大家都默认采用 COOKIE 的方式。
服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对COOKIE来说更安全,
可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
3。token
token的意思是“令牌”,是用户身份的验证方式.
最简单的token组成:
【1】uid(用户唯一的身份标识)
【2】time(当前时间的时间戳)
【3】sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,
可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库
这里的token是指SON Web Token
用户注册之后, 服务器生成一个 JWT token返回给浏览器, 浏览器向服务器请求数据时将 JWT token 发给服务器,
服务器用 signature 中定义的方式解码
WT 获取用户信息.
一个 JWT token包含3部分:
【1】header: 告诉我们使用的算法和 token 类型
【2】Payload: 必须使用 sub key 来指定用户 ID, 还可以包括其他信息比如 email, username 等.
【3】Signature: 用来保证 JWT 的真实性. 可以使用不同算法
二。jwt(json web token)权限验证
完整代码:
1 package main
2
3 import (
4 "log"
5 "net/http"
6 "github.com/codegangsta/negroni"
7 "encoding/json"
8 "fmt"
9 "strings"
10 "github.com/dgrijalva/jwt-go"
11 "time"
12 "github.com/dgrijalva/jwt-go/request"
13 )
14
15 /**
16 说明:
17 客户端通过在request对象header里添加token参数,发送到服务端。
18 服务端再拿出token进行比对。
19 token的第一次产生是发生在login检查账户存在并且正确之后,为该用户赋予一块令牌(加密字符串)
20 并将token放入response的header里。客户端登陆成功后,从response里取出token。并在以后操作request请求。
21 都保持在header里添加该段令牌,令牌有效期失效后,只有重新login,才能获取新的令牌。
22 */
23 const (
24 //SecretKey = "welcome to wangshubo's blog"
25 SecretKey = "I have login"
26 )
27
28 func fatal(err error) {
29 if err != nil {
30 log.Fatal(err)
31 }
32 }
33
34 type UserCredentials struct {
35 Username string `json:"username"`
36 Password string `json:"password"`
37 }
38
39 type User struct {
40 ID int `json:"id"`
41 Name string `json:"name"`
42 Username string `json:"username"`
43 Password string `json:"password"`
44 }
45
46 type Response struct {
47 Data string `json:"data"`
48 }
49
50 type Token struct {
51 Token string `json:"token"`
52 }
53
54 func StartServer() {
55
56 http.HandleFunc("/login", LoginHandler)
57
58 http.Handle("/resource", negroni.New(
59 negroni.HandlerFunc(ValidateTokenMiddleware),
60 negroni.Wrap(http.HandlerFunc(ProtectedHandler)),
61 ))
62
63 log.Println("Now listening...")
64 http.ListenAndServe(":8080", nil)
65 }
66
67 func main() {
68 StartServer()
69 }
70
71 func ProtectedHandler(w http.ResponseWriter, r *http.Request) {
72
73 response := Response{"Gained access to protected resource !"}
74 JsonResponse(response, w)
75
76 }
77
78 //服务端生成token,并放入到response的header
79 /**
80 JWT由三部份组成:
81 * Header:头部 (对应:Header)
82 * Claims:声明 (对应:Payload)
83 * Signature:签名 (对应:Signature)
84 */
85 func LoginHandler(w http.ResponseWriter, r *http.Request) {
86
87 var u *User=new(User)
88
89 var user UserCredentials
90
91 err := json.NewDecoder(r.Body).Decode(&user)
92
93 if err != nil {
94 w.WriteHeader(http.StatusForbidden)
95 fmt.Fprint(w, "Error in request")
96 return
97 }
98
99 //验证是身份:若用户是someone,则生成token
100 if strings.ToLower(user.Username) != "someone" {
101 if user.Password != "p@ssword" {
102 w.WriteHeader(http.StatusForbidden)
103 fmt.Println("Error logging in")
104 fmt.Fprint(w, "Invalid credentials")
105 return
106 }
107 }
108
109 //1。生成token
110 token := jwt.New(jwt.SigningMethodHS256)
111 claims := make(jwt.MapClaims)
112 //2。添加令牌关键信息
113 //添加令牌期限
114 claims["exp"] = time.Now().Add(time.Hour * time.Duration(1)).Unix()
115 claims["iat"] = time.Now().Unix()
116 claims["id"]=u.ID
117 claims["userName"]=u.Username
118 claims["password"]=u.Password
119 token.Claims = claims
120
121 fmt.Println(claims)
122
123 if err != nil {
124 w.WriteHeader(http.StatusInternalServerError)
125 fmt.Fprintln(w, "Error extracting the key")
126 fatal(err)
127 }
128
129 //获取令牌
130 tokenString, err := token.SignedString([]byte(SecretKey))
131 if err != nil {
132 w.WriteHeader(http.StatusInternalServerError)
133 fmt.Fprintln(w, "Error while signing the token")
134 fatal(err)
135 }
136
137 //2。将生成的token放入到header
138 response := Token{tokenString}
139 JsonResponse(response, w)
140
141 }
142
143 //验证Token
144 func ValidateTokenMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
145 token, err := request.ParseFromRequest(r, request.AuthorizationHeaderExtractor,
146 func(token *jwt.Token) (interface{}, error) {
147 return []byte(SecretKey), nil
148 })
149
150 if err == nil {
151 if token.Valid {
152 next(w, r)
153 } else {
154 w.WriteHeader(http.StatusUnauthorized)
155 fmt.Fprint(w, "Token is not valid")
156 }
157 } else {
158 w.WriteHeader(http.StatusUnauthorized)
159 fmt.Fprint(w, "Unauthorized access to this resource")
160 }
161
162 }
163
164 func JsonResponse(response interface{}, w http.ResponseWriter) {
165 json, err := json.Marshal(response)
166 if err != nil {
167 http.Error(w, err.Error(), http.StatusInternalServerError)
168 return
169 }
170 w.WriteHeader(http.StatusOK)
171 w.Header().Set("Content-Type", "application/json")
172 w.Write(json)
173 }
View Code