Gin Practice Five Build blog API ' s (iv)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

API ' S-json Web Tokens (JWT)

In the previous sections, we have basically completed the writing of the API ' s

However, there are some very serious problems, for example, our current API can be arbitrarily called, which is obviously not perfect enough, there is a problem

Then we use Jwt-go (Godoc) To solve this problem in a simple way.

Download Dependent packages

First, we download the Jwt-go dependency package

go get -u github.com/dgrijalva/jwt-go

Authoring jwt Toolkit

We need to write a jwt toolkit that we created in the pkg next util directory jwt.go to write the contents of the file:

Package Utilimport ("Time" JWT "Github.com/dgrijalva/jwt-go" "gin-blog/pkg/setting") var jwtsecret = []byte (Setti Ng. Jwtsecret) type Claims struct {Username string ' JSON: ' Username ' ' Password string ' json: ' Password ' ' JWT. Standardclaims}func generatetoken (username, password string) (string, error) {nowtime: = time. Now () Expiretime: = Nowtime.add (3 * time. Hour) Claims: = claims{username, password, JWT. standardclaims {ExpiresAt:expireTime.Unix (), Issuer: "Gin-blog",},} Tokenclaims: = JWT. Newwithclaims (JWT. SIGNINGMETHODHS256, claims) token, err: = Tokenclaims.signedstring (Jwtsecret) return token, Err}func Parsetoken (toke n String (*claims, error) {tokenclaims, err: = JWT. Parsewithclaims (token, &claims{}, func (token *JWT). Token) (interface{}, error) {return jwtsecret, nil}) if tokenclaims! = nil {if claims, OK: = Tokenc Laims. Claims. (*claims); OK && tokenclaims. Valid {return claims, nil}} return nil, err}

In this toolkit, we relate

    • NewWithClaims(method SigningMethod, claims Claims), which method corresponds SigningMethodHMAC struct{} to, including SigningMethodHS256 , SigningMethodHS384 SigningMethodHS512 Three kinds of crypto.Hash solutions
    • func (t *Token) SignedString(key interface{})The method internally generates the signature string, which is then used to obtain the full, signedtoken
    • func (p *Parser) ParseWithClaimsA declaration used for parsing authentication, which is essentially a process of decoding and verifying, ultimately returning*Token
    • func (m MapClaims) Valid()Verify time-based claims exp, iat, nbf , and note that if there are no claims in the token, it will still be considered valid. And there is no calculation method for time zone deviations

With the jwt toolkit, we're going to write the middleware we're going to use Gin , we'll middleware create a new jwt directory, create a new jwt.go file, write the content:

package jwtimport (    "time"    "net/http"    "github.com/gin-gonic/gin"    "gin-blog/pkg/util"    "gin-blog/pkg/e")func JWT() gin.HandlerFunc {    return func(c *gin.Context) {        var code int        var data interface{}        code = e.SUCCESS        token := c.Query("token")        if token == "" {            code = e.INVALID_PARAMS        } else {            claims, err := util.ParseToken(token)            if err != nil {                code = e.ERROR_AUTH_CHECK_TOKEN_FAIL            } else if time.Now().Unix() > claims.ExpiresAt {                code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT            }        }        if code != e.SUCCESS {            c.JSON(http.StatusUnauthorized, gin.H{                "code" : code,                "msg" : e.GetMsg(code),                "data" : data,            })            c.Abort()            return        }        c.Next()    }}

How to getToken

So how do we call it, and what else do we get Token ?

1, we want to add a Get Token API

modelsunder Create a new auth.go file, write the content:

package modelstype Auth struct {    ID int `gorm:"primary_key" json:"id"`    Username string `json:"username"`    Password string `json:"password"`}func CheckAuth(username, password string) bool {    var auth Auth    db.Select("id").Where(Auth{Username : username, Password : password}).First(&auth)    if auth.ID > 0 {        return true    }    return false}

In the routers next api directory, create a new auth.go file, write the content:

Package Apiimport ("Log" "Net/http" "Github.com/gin-gonic/gin" "Github.com/astaxie/beego/validation" "gin- blog/pkg/e "" Gin-blog/pkg/util "" gin-blog/models ") type auth struct {Username string ' valid:" Required; MaxSize () "' Password string ' valid: Required; MaxSize () "'}func GetAuth (c *gin. Context) {username: = C.query ("username") Password: = c.query ("password") Valid: = Validation. validation{} A: = Auth{username:username, Password:password} OK, _: = valid. Valid (&a) Data: = Make (map[string]interface{}) Code: = E.invalid_params If ok {isexist: = models. Checkauth (username, password) If isexist {token, err: = util.                Generatetoken (username, password) if err! = Nil {code = E.error_auth_token} else {            data["token"] = token code = e.success}} else {        Code = E.error_auth}} else {For _, Err: = range valid. Errors {log. Println (Err. Key, Err. Message)}} c.json (http. Statusok, Gin. h{"Code": Code, "MSG": E.getmsg (Code), "Data": Data,})}

We open the routers file in the directory router.go , modify the contents of the file (new method to obtain token):

package routersimport (    "github.com/gin-gonic/gin"        "gin-blog/routers/api"    "gin-blog/routers/api/v1"    "gin-blog/pkg/setting")func InitRouter() *gin.Engine {    r := gin.New()    r.Use(gin.Logger())    r.Use(gin.Recovery())    gin.SetMode(setting.RunMode)    r.GET("/auth", api.GetAuth)    apiv1 := r.Group("/api/v1")    {        ...    }    return r}

VerifyToken

Get token The API method is here, let us test whether it can be used properly!

After restarting the service, use GET the method http://127.0.0.1:8000/auth?username=test&password=test123456 to access and see if the return value is correct

{  "code": 200,  "data": {    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QxMjM0NTYiLCJleHAiOjE1MTg3MjAwMzcsImlzcyI6Imdpbi1ibG9nIn0.-kK0V9E06qTHOzupQM_gHXAGDB3EJtJS4H5TTCyWwW8"  },  "msg": "ok"}

We have token the API, and also the call succeeded

Access to middlewareGin

2. Next, we will access the middleware into Gin the access process

We open the routers file in the directory router.go , modify the contents of the file (new reference package and middleware reference)

package routersimport (    "github.com/gin-gonic/gin"        "gin-blog/routers/api"    "gin-blog/routers/api/v1"    "gin-blog/pkg/setting"    "gin-blog/middleware/jwt")func InitRouter() *gin.Engine {    r := gin.New()    r.Use(gin.Logger())    r.Use(gin.Recovery())    gin.SetMode(setting.RunMode)    r.GET("/auth", api.GetAuth)    apiv1 := r.Group("/api/v1")    apiv1.Use(jwt.JWT())    {        ...    }    return r}

Current directory structure:

gin-blog/├── conf│   └── app.ini├── main.go├── middleware│   └── jwt│       └── jwt.go├── models│   ├── article.go│   ├── auth.go│   ├── models.go│   └── tag.go├── pkg│   ├── e│   │   ├── code.go│   │   └── msg.go│   ├── setting│   │   └── setting.go│   └── util│       ├── jwt.go│       └── pagination.go├── routers│   ├── api│   │   ├── auth.go│   │   └── v1│   │       ├── article.go│   │       └── tag.go│   └── router.go├── runtime

Here, our JWT writing is done!

Validation features

Let's test it and visit it again.

    • Http://127.0.0.1:8000/api/v1/articles
    • http://127.0.0.1:8000/api/v1/articles?token=23131

The correct feedback should be

{  "code": 400,  "data": null,  "msg": "请求参数错误"}{  "code": 20001,  "data": null,  "msg": "Token鉴权失败"}

We need access http://127.0.0.1:8000/auth?username=test&password=test123456 to gettoken

{  "code": 200,  "data": {    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QxMjM0NTYiLCJleHAiOjE1MTg3MjQ2OTMsImlzcyI6Imdpbi1ibG9nIn0.KSBY6TeavV_30kfmP7HWLRYKP5TPEDgHtABe9HCsic4"  },  "msg": "ok"}

Then use token the included URL parameter to access our app API,

Access http://127.0.0.1:8000/api/v1/articles?token=eyJhbGci... , check the interface return value

{  "code": 200,  "data": {    "lists": [      {        "id": 2,        "created_on": 1518700920,        "modified_on": 0,        "tag_id": 1,        "tag": {          "id": 1,          "created_on": 1518684200,          "modified_on": 0,          "name": "tag1",          "created_by": "",          "modified_by": "",          "state": 0        },        "content": "test-content",        "created_by": "test-created",        "modified_by": "",        "state": 0      }    ],    "total": 1  },  "msg": "ok"}

Back to the right, so our jwt-go verification in in is Gin done!

Reference

Sample code for this series

    • Go-gin-example
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.