使用JWT做RESTful API的身份验证-Go语言实现

简介: 在 使用Golang和MongoDB构建 RESTful API已经实现了一个简单的 RESTful API应用,但是对于有些API接口需要授权之后才能访问,在这篇文章中就用 jwt 做一个基于Token的身份验证,关于 jwt 请访问 JWT有详细的说明,而且有各个语言实现的库,请根据需要使用对应的版本。

在 使用Golang和MongoDB构建 RESTful API已经实现了一个简单的 RESTful API应用,但是对于有些API接口需要授权之后才能访问,在这篇文章中就用 jwt 做一个基于Token的身份验证,关于 jwt 请访问 JWT有详细的说明,而且有各个语言实现的库,请根据需要使用对应的版本。

需要先安装 jwt-go 接口 go get github.com/dgrijalva/jwt-go
新增注册登录接口,并在登录时生成token

自定义返回结果,并封装 helper/utils.go

1type Response struct {
 2    Code int         `json:"code"`
 3    Msg  string      `json:"msg"`
 4    Data interface{} `json:"data"`
 5}
 6
 7func ResponseWithJson(w http.ResponseWriter, code int, payload interface{}) {
 8    response, _ := json.Marshal(payload)
 9    w.Header().Set("Content-Type", "application/json")
10    w.WriteHeader(code)
11    w.Write(response)
12}

模型 models/user.go

1type User struct {
2    UserName string `bson:"username" json:"username"`
3    Password string `bson:"password" json:"password"`
4}type JwtToken struct {
5    Token string `json:"token"`
6}

控制器 controllers/user.go

1func Register(w http.ResponseWriter, r *http.Request) {
 2    var user models.User
 3    err := json.NewDecoder(r.Body).Decode(&user)    if err != nil || user.UserName == "" || user.Password == "" {
 4        helper.ResponseWithJson(w, http.StatusBadRequest,
 5            helper.Response{Code: http.StatusBadRequest, Msg: "bad params"})        return
 6    }
 7    err = models.Insert(db, collection, user)   if err != nil {
 8        helper.ResponseWithJson(w, http.StatusInternalServerError,
 9            helper.Response{Code: http.StatusInternalServerError, Msg: "internal error"})
10    }
11}
12
13func Login(w http.ResponseWriter, r *http.Request) {
14    var user models.User
15    err := json.NewDecoder(r.Body).Decode(&user)    if err != nil {
16        helper.ResponseWithJson(w, http.StatusBadRequest,
17            helper.Response{Code: http.StatusBadRequest, Msg: "bad params"})
18    }
19    exist := models.IsExist(db, collection, bson.M{"username": user.UserName})  if exist {
20        token, _ := auth.GenerateToken(&user)
21        helper.ResponseWithJson(w, http.StatusOK,
22            helper.Response{Code: http.StatusOK, Data: models.JwtToken{Token: token}})
23    } else {
24        helper.ResponseWithJson(w, http.StatusNotFound,
25            helper.Response{Code: http.StatusNotFound, Msg: "the user not exist"})
26    }
27}

生成Token auth/middleware.go

1func GenerateToken(user *models.User) (string, error) {
2    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{       "username": user.UserName,
3    //"exp":      time.Now().Add(time.Hour * 2).Unix(),// 可以添加过期时间
4    })  return token.SignedString([]byte("secret"))//对应的字符串请自行生成,最后足够使用加密后的字符串
5}

http中间件
go http的中间件实现起来很简单,只需要实现一个函数签名func(http.Handler) http.Handler的函数即可。

1func middlewareHandler(next http.Handler) http.Handler{    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
2        // 执行handler之前的逻辑
3        next.ServeHTTP(w, r)
4        // 执行完毕handler后的逻辑
5    })
6}

我们使用的 mux 作为路由,本身支持在路由中添加中间件,改造一下之前的路由逻辑
routes/routes.go

1type Route struct {
2    Method     string
3    Pattern    string
4    Handler    http.HandlerFunc
5    Middleware mux.MiddlewareFunc //添加中间件
6}
7
8func NewRouter() *mux.Router {
9    router := mux.NewRouter()   for _, route := range routes {
10        r := router.Methods(route.Method).
11            Path(route.Pattern)
12    //如果这个路由有中间件的逻辑,需要通过中间件先处理一下        if route.Middleware != nil {
13            r.Handler(route.Middleware(route.Handler))
14        } else {
15            r.Handler(route.Handler)
16        }
17    }   return router
18}

实现身份验证的中间件
auth/middleware.go
验证的信息放在http Header中

1func TokenMiddleware(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 2        tokenStr := r.Header.Get("authorization")       if tokenStr == "" {
 3            helper.ResponseWithJson(w, http.StatusUnauthorized,
 4                helper.Response{Code: http.StatusUnauthorized, Msg: "not authorized"})
 5        } else {
 6            token, _ := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {               if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
 7                    helper.ResponseWithJson(w, http.StatusUnauthorized,
 8                        helper.Response{Code: http.StatusUnauthorized, Msg: "not authorized"})                  return nil, fmt.Errorf("not authorization")
 9                }               return []byte("secret"), nil
10            })          if !token.Valid {
11                helper.ResponseWithJson(w, http.StatusUnauthorized,
12                    helper.Response{Code: http.StatusUnauthorized, Msg: "not authorized"})
13            } else {
14                next.ServeHTTP(w, r)
15            }
16        }
17    })
18}

对需要验证的路由添加中间件

1register("GET", "/movies", controllers.AllMovies, auth.TokenMiddleware) //需要中间件逻辑
2register("GET", "/movies/{id}", controllers.FindMovie, nil)//不需要中间件复制代码

验证
登录之后,返回对应的token信息

1//请求 post http://127.0.0.1:8080/login
2//返回
3
4{    "code": 200,    "msg": "",    "data": {        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvZGVybWluZXIifQ.pFzJLU8vnzWiweFKzHRsawyWA2jfuDIPlDU4zE92O7c"
5    }
6}

获取所有的电影信息时

1//请求 post http://127.0.0.1:8080/movies
2在 Header中设置 "authorization":token
3如果没有设置header会报 401 错误
4
5{    "code": 401,    "msg": "not authorized",    "data": null
6}

源码 Github

原文发布时间为:2018-07-19
本文作者:CoderMiner
本文来自云栖社区合作伙伴“Golang语言社区”,了解相关信息可以关注“Golang语言社区

相关文章
|
2月前
|
JSON JavaScript 前端开发
深入浅出Node.js:从零开始构建RESTful API
在数字化时代的浪潮中,后端开发作为连接用户与数据的桥梁,扮演着至关重要的角色。本文将引导您步入Node.js的奇妙世界,通过实践操作,掌握如何使用这一强大的JavaScript运行时环境构建高效、可扩展的RESTful API。我们将一同探索Express框架的使用,学习如何设计API端点,处理数据请求,并实现身份验证机制,最终部署我们的成果到云服务器上。无论您是初学者还是有一定基础的开发者,这篇文章都将为您打开一扇通往后端开发深层知识的大门。
71 12
|
3月前
|
XML JSON 缓存
深入理解RESTful API设计原则与实践
在现代软件开发中,构建高效、可扩展的应用程序接口(API)是至关重要的。本文旨在探讨RESTful API的核心设计理念,包括其基于HTTP协议的特性,以及如何在实际应用中遵循这些原则来优化API设计。我们将通过具体示例和最佳实践,展示如何创建易于理解、维护且性能优良的RESTful服务,从而提升前后端分离架构下的开发效率和用户体验。
|
3月前
|
JSON 缓存 测试技术
构建高效RESTful API的后端实践指南####
本文将深入探讨如何设计并实现一个高效、可扩展且易于维护的RESTful API。不同于传统的摘要概述,本节将直接以行动指南的形式,列出构建RESTful API时必须遵循的核心原则与最佳实践,旨在为开发者提供一套直接可行的实施框架,快速提升API设计与开发能力。 ####
|
3月前
|
JSON API 开发者
深入理解RESTful API设计原则
在数字化时代,API已成为连接不同软件应用的桥梁。本文旨在探讨RESTful API设计的基本原则和最佳实践,帮助开发者构建高效、可扩展的网络服务接口。通过解析REST架构风格的核心概念,我们将了解如何设计易于理解和使用的API,同时保证其性能和安全性。
|
3月前
|
存储 缓存 API
深入理解RESTful API设计原则
在现代软件开发中,RESTful API已成为前后端分离架构下不可或缺的通信桥梁。本文旨在探讨RESTful API的核心设计原则,包括资源导向、无状态、统一接口、以及可缓存性等,并通过实例解析如何在实际应用中遵循这些原则来构建高效、可维护的API接口。我们将深入分析每个原则背后的设计理念,提供最佳实践指导,帮助开发者优化API设计,提升系统整体性能和用户体验。
60 0
|
2月前
|
JSON 安全 Java
什么是JWT?如何使用Spring Boot Security实现它?
什么是JWT?如何使用Spring Boot Security实现它?
482 5
|
6月前
|
SQL Java 测试技术
在Spring boot中 使用JWT和过滤器实现登录认证
在Spring boot中 使用JWT和过滤器实现登录认证
333 0
|
4月前
|
JSON 安全 算法
|
1月前
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
87 11
|
1月前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
369 12

热门文章

最新文章