Using JWT to do the authentication of RESTful API-go language implementation
Building a restful API with Golang and MongoDB has already implemented a simple RESTful API application, but for some API interfaces that require authorization before they can be accessed, jwt a token-based authentication is used in this article about jwt Please visit JWT for detailed instructions, and there are libraries implemented in each language, please use the corresponding version as needed.
Image
The interface needs to be installed first jwt-gogo get github.com/dgrijalva/jwt-go
Added sign-in interface and token creation at login
- Customize the return results and encapsulate
helper/utils.go
type Response struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"`}func ResponseWithJson(w http.ResponseWriter, code int, payload interface{}) { response, _ := json.Marshal(payload) w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) w.Write(response)}
type User struct { UserName string `bson:"username" json:"username"` Password string `bson:"password" json:"password"`}type JwtToken struct { Token string `json:"token"`}
- Controller
controllers/user.go
Func Register (w http. Responsewriter, R *http. Request) {var user models. User ERR: = json. Newdecoder (R.body). Decode (&user) if err! = Nil | | User. UserName = = "" | | User. Password = = "" {Helper. Responsewithjson (W, http. Statusbadrequest, Helper. Response{code:http. Statusbadrequest, MSG: "Bad Params"}) return} err = models. Insert (DB, collection, user) if err! = Nil {helper. Responsewithjson (W, http. Statusinternalservererror, Helper. Response{code:http. Statusinternalservererror, MSG: "Internal Error"})}}func Login (w http. Responsewriter, R *http. Request) {var user models. User ERR: = json. Newdecoder (R.body). Decode (&user) if err! = Nil {helper. Responsewithjson (W, http. Statusbadrequest, Helper. Response{code:http. Statusbadrequest, MSG: "Bad Params"})} exist: = models. Isexist (DB, Collection, Bson. m{"username": User. UserName}) if exist {token, _: = Auth. Generatetoken (&user) Helper. Responsewithjson (W, http. Statusok, Helper. Response{code:http. Statusok, Data:models. Jwttoken{token:token}})} else {helper. Responsewithjson (W, http. Statusnotfound, Helper. Response{code:http. Statusnotfound, MSG: "The User not Exist"})}}
- Generate tokens
auth/middleware.go
func GenerateToken(user *models.User) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "username": user.UserName, //"exp": time.Now().Add(time.Hour * 2).Unix(),// 可以添加过期时间 }) return token.SignedString([]byte("secret"))//对应的字符串请自行生成,最后足够使用加密后的字符串}
HTTP middleware
The middleware of Go HTTP is very simple to implement, just to implement a function signature as func (http. Handler) http. The handler function can be.
func middlewareHandler(next http.Handler) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ // 执行handler之前的逻辑 next.ServeHTTP(w, r) // 执行完毕handler后的逻辑 })}
We use the MUX as a route, which natively supports the addition of middleware in the route, transforming the previous routing logic
routes/routes.go
type Route struct { Method string Pattern string Handler http.HandlerFunc Middleware mux.MiddlewareFunc //添加中间件}func NewRouter() *mux.Router { router := mux.NewRouter() for _, route := range routes { r := router.Methods(route.Method). Path(route.Pattern) //如果这个路由有中间件的逻辑,需要通过中间件先处理一下 if route.Middleware != nil { r.Handler(route.Middleware(route.Handler)) } else { r.Handler(route.Handler) } } return router}
Middleware for implementing authentication
auth/middleware.go
Verify that the information is placed in the http Header
Func tokenmiddleware (next http. Handler) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {tokenstr: = R.header.get ("authorization") if Tokenstr = = "" {Helper. Responsewithjson (W, http. statusunauthorized, Helper. Response{code:http. statusunauthorized, MSG: "Not Authorized"})} else {token, _: = JWT. Parse (Tokenstr, func (token *JWT). token) (interface{}, error) {If _, OK: = token. Method. (*JWT. SIGNINGMETHODHMAC);!ok {Helper. Responsewithjson (W, http. statusunauthorized, Helper. Response{code:http. statusunauthorized, MSG: "Not Authorized"}) return nil, FMT. Errorf ("Not Authorization")} Return []byte ("secret"), nil}) if!toke N.valid {Helper. Responsewithjson (W, http. statusunauthorized, Helper. Response{code:http. Statusunauthorized, MSG: "Not Authorized"})} else {next. Servehttp (W, R)}})}
Adding middleware to routes that require validation
register("GET", "/movies", controllers.AllMovies, auth.TokenMiddleware) //需要中间件逻辑register("GET", "/movies/{id}", controllers.FindMovie, nil)//不需要中间件
Verify
- After logging in, return the corresponding token information
//请求 post http://127.0.0.1:8080/login//返回{ "code": 200, "msg": "", "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvZGVybWluZXIifQ.pFzJLU8vnzWiweFKzHRsawyWA2jfuDIPlDU4zE92O7c" }}
- Get all the movie information when
//请求 post http://127.0.0.1:8080/movies在 Header中设置 "authorization":token如果没有设置header会报 401 错误{ "code": 401, "msg": "not authorized", "data": null}
SOURCE Github