JWT实现基于token的鉴权
JWT实现基于token的鉴权
一.介绍
- 1.JSON Web Token,简称JWT,本质是一个token,是一种紧凑的URL安全方法,用于在网络通信的双方之间传递。
- 2.一般放在HTTP的headers 参数里面的authorization里面,值的前面加Bearer关键字和空格。
- 3.主要用于身份认证和信息交换
- 4.由三部分组成,用英文句点连接(.),例如:xxxxxx.yyyyyy.zzzzzz
二.JWT的结构:JWT是三段(header.payload.signature)由小数点组成的字符串
a)header:头部用于描述关于JWT的基本的信息(如:类型,签名算法):
- <span style="color:rgb(0,0,0);"><span style="font-size:14px;">{
- "alg": "HS256",
- "typ": "JWT"
- }</span></span>
b)payload:包含claims(有三种:标准中注册的声明,公共声明,私有声明)的消息体:
标准中注册的声明,建议但不强制使用:
>iss: jwt的签发者
>sub: jwt所面向的用户
>aud: 接收该jwt的一方
> exp: jwt的过期时间
> nbf: 在该时间之前,该jwt都是不可用的
> iat:jwt签发时间
> jti:jwt的ID
- <span style="color:rgb(0,0,0);"><span style="font-size:14px;">{
- "sub": "1234567890",
- "name": "John Doe",
- "admin": true
- }</span></span>
生成过程:
第一部分:将header的json对象进行base64编码
第二部分:将payload的json对象进行base64编码
第三部分:将拼接好的前两部分使用签名算法加密
更详细的介绍:
https://jwt.io/introduction/
https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32
(2)验证流程:
- 1.首次登录:提交用户名密码
- 2.密码验证:通过后根据用户信息生成JWT
- 3.返回JWT:把JWT返回客户端,设置cookie或者设置到http请求头的Authorization中(一般是在请求头里加入Authorization并加上Bearer标注)
- 4.带JWT请求:每次访问服务器的时候都携带JWT,服务器根据JWT进行验证是否被篡改,没有的话获取信息
二.简单使用(使用jwt-go:https://github.com/dgrijalva/jwt-go)
- <span style="font-size:14px;">//密匙
- const (
- SecretKey = "welcome"
- )
- //错误处理
- 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)
- }
- //登录获取token
- 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 != "password" {
- 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)
- }
- //验证token
- 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)
- }</span>
转自https://blog.****.net/simatongming/article/details/79102597
一.介绍
- 1.JSON Web Token,简称JWT,本质是一个token,是一种紧凑的URL安全方法,用于在网络通信的双方之间传递。
- 2.一般放在HTTP的headers 参数里面的authorization里面,值的前面加Bearer关键字和空格。
- 3.主要用于身份认证和信息交换
- 4.由三部分组成,用英文句点连接(.),例如:xxxxxx.yyyyyy.zzzzzz
二.JWT的结构:JWT是三段(header.payload.signature)由小数点组成的字符串
a)header:头部用于描述关于JWT的基本的信息(如:类型,签名算法):
- <span style="color:rgb(0,0,0);"><span style="font-size:14px;">{
- "alg": "HS256",
- "typ": "JWT"
- }</span></span>
b)payload:包含claims(有三种:标准中注册的声明,公共声明,私有声明)的消息体:
标准中注册的声明,建议但不强制使用:
>iss: jwt的签发者
>sub: jwt所面向的用户
>aud: 接收该jwt的一方
> exp: jwt的过期时间
> nbf: 在该时间之前,该jwt都是不可用的
> iat:jwt签发时间
> jti:jwt的ID
- <span style="color:rgb(0,0,0);"><span style="font-size:14px;">{
- "sub": "1234567890",
- "name": "John Doe",
- "admin": true
- }</span></span>
生成过程:
第一部分:将header的json对象进行base64编码
第二部分:将payload的json对象进行base64编码
第三部分:将拼接好的前两部分使用签名算法加密
更详细的介绍:
https://jwt.io/introduction/
https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32
(2)验证流程:
- 1.首次登录:提交用户名密码
- 2.密码验证:通过后根据用户信息生成JWT
- 3.返回JWT:把JWT返回客户端,设置cookie或者设置到http请求头的Authorization中(一般是在请求头里加入Authorization并加上Bearer标注)
- 4.带JWT请求:每次访问服务器的时候都携带JWT,服务器根据JWT进行验证是否被篡改,没有的话获取信息
二.简单使用(使用jwt-go:https://github.com/dgrijalva/jwt-go)
- <span style="font-size:14px;">//密匙
- const (
- SecretKey = "welcome"
- )
- //错误处理
- 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)
- }
- //登录获取token
- 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 != "password" {
- 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)
- }
- //验证token
- 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)
- }</span>
转自https://blog.****.net/simatongming/article/details/79102597