- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章前后端分离必备, Golang Gin中如何使用JWT(JsonWebToken)中间件?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
什么是JWT?
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,也是目前前后端分离项目中普遍使用的认证技术. 本文介绍如何在Golang Gin Web框架中使用JWT认证中间件以及模拟测试, 以供参考, 关于JWT详细原理可以参考
主要流程 。
流程图 。
该流程图描述了服务端代码中的Token构造, 以及认证流程. 。
服务端代码 。
main.go中填充以下代码, 运行go run main.go, 开启Web服务. 。
package main 。
。
import ( 。
jwt_lib "github.com/dgrijalva/jwt-go" 。
"github.com/dgrijalva/jwt-go/request" 。
"github.com/gin-gonic/gin" 。
"log" 。
"time" 。
) 。
。
var ( 。
mysupersecretpassword = "unicornsAreAwesome" 。
) 。
。
func Auth(secret string) gin.HandlerFunc { 。
return func(c *gin.Context) { 。
//log.Printf("Request:\n%+v", c.Request) 。
// ParseFromRequest方法提取路径请求中的JWT令牌, 并进行验证 。
token, err := request.ParseFromRequest(c.Request, request.OAuth2Extractor, func(token *jwt_lib.Token) (interface{}, error) { 。
b := ([]byte(secret)) 。
//log.Printf("b:%+v", b) 。
return b, nil 。
}) 。
。
log.Printf("token:%+v", token) 。
if err != nil { 。
c.AbortWithError(401, err) 。
} 。
} 。
} 。
。
func main() { 。
r := gin.Default() 。
。
public := r.Group("/api") 。
。
// 定义根路由, 访问http://locahost:8080/api/可以获取到token 。
public.GET("/", func(c *gin.Context) { 。
// Create the token New方法接受一个签名方法的接口类型(SigningMethod)参数, 返回一个Token结构指针 。
// GetSigningMethod(签名算法algorithm) 。
token := jwt_lib.New(jwt_lib.GetSigningMethod("HS256")) //默认是签名算法是HMAC SHA256(写成 HS256) 。
log.Printf("token:%+v", token) 。
//2020/12/10 22:32:02 token:&{Raw: Method:0xc00000e2a0 Header:map[alg:HS256 typ:JWT] Claims:map[] Signature: Valid:false} 。
。
// Set some claims 设置Id和过期时间字段, MapClaims实现了Clainms接口 。
token.Claims = jwt_lib.MapClaims{ 。
"Id": "Christopher", 。
"exp": time.Now().Add(time.Hour * 1).Unix(), 。
} 。
// Sign and get the complete encoded token as a string // 签名并得到完整编码后的Token字符串 。
tokenString, err := token.SignedString([]byte(mysupersecretpassword)) 。
//{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IkNocmlzdG9waGVyIiwiZXhwIjoxNjA3NjE0MzIyfQ.eQd7ztDn3706GrpitgnikKgOtzx-RHnq7cr2eqUlsZo"} 。
if err != nil { 。
c.JSON(500, gin.H{"message": "Could not generate token"}) 。
} 。
c.JSON(200, gin.H{"token": tokenString}) 。
}) 。
。
// 定义需要Token验证通过才能访问的私有接口组http://localhost:8080/api/private 。
private := r.Group("/api/private") 。
private.Use(Auth(mysupersecretpassword)) // 使用JWT认证中间件(带参数) 。
。
/* 。
Set this header in your request to get here. 。
Authorization: Bearer `token` 。
*/ 。
。
// 定义具体的私有根接口:http://localhost:8080/api/private/ 。
private.GET("/", func(c *gin.Context) { 。
c.JSON(200, gin.H{"message": "Hello from private"}) 。
}) 。
。
r.Run("localhost:8080") 。
} 。
客户端代码 。
新建jwt_test.go文件, 填充以下代码, 运行go test执行单元测试. 。
package test_test 。
。
import ( 。
"encoding/json" 。
. "github.com/smartystreets/goconvey/convey" //https://github.com/smartystreets/goconvey GoConvey是Golang的测试框架,集成go test, 支持终端和浏览器模式. 。
"io/ioutil" 。
"log" 。
"net/http" 。
"strings" 。
"testing" 。
) 。
。
type User struct { 。
Username string `json:"username"` 。
Password string `json:"password"` 。
} 。
。
type Response struct { 。
Token string `json:"token"` 。
} 。
。
func createNewsUser(username, password string) *User { 。
return &User{username, password} 。
} 。
。
func TestLogin(t *testing.T) { 。
Convey("Should be able to login", t, func() { 。
user := createNewsUser("jonas", "1234") 。
jsondata, _ := json.Marshal(user) 。
userData := strings.NewReader(string(jsondata)) 。
log.Printf("userData:%+v", userData) 。
// 这里模拟用户登录, 实际上后台没有使用用户名和密码, 该接口直接返回内部生成的Token 。
req, _ := http.NewRequest("GET", "http://localhost:8080/api/", userData) 。
req.Header.Set("Content-Type", "application/json") 。
client := &http.Client{} 。
res, _ := client.Do(req) 。
//log.Printf("res:%+v", res) 。
So(res.StatusCode, ShouldEqual, 200) //对响应码进行断言, 期望得到状态码为200 。
。
Convey("Should be able to parse body", func() { //解析响应体 。
body, err := ioutil.ReadAll(res.Body) 。
defer res.Body.Close() 。
So(err, ShouldBeNil) 。
Convey("Should be able to get json back", func() { 。
responseData := new(Response) 。
err := json.Unmarshal(body, responseData) 。
So(err, ShouldBeNil) 。
log.Printf("responseData:%s", responseData) 。
Convey("Should be able to be authorized", func() { 。
token := responseData.Token //提取Token 。
log.Printf("token:%s", token) 。
// 构造带Token的请求 。
req, _ := http.NewRequest("GET", "http://localhost:8080/api/private", nil) 。
req.Header.Set("Authorization", "Bearer "+token) //设置认证头 。
client = &http.Client{} 。
res, _ := client.Do(req) 。
body, err := ioutil.ReadAll(res.Body) 。
if err != nil { 。
log.Printf("Read body failed, %s", err.Error()) 。
} 。
log.Printf("Body:%s", string(body)) 。
So(res.StatusCode, ShouldEqual, 200) 。
}) 。
}) 。
}) 。
}) 。
} 。
参考文档 。
gin-gonic/contrib/jwt中间件: https://github.com/gin-gonic/contrib/tree/master/jwt 。
原文地址:https://mp.weixin.qq.com/s/dEptFz4KTrPczZB-K4AiKg最后此篇关于前后端分离必备, Golang Gin中如何使用JWT(JsonWebToken)中间件?的文章就讲到这里了,如果你想了解更多关于前后端分离必备, Golang Gin中如何使用JWT(JsonWebToken)中间件?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有很多路线,从 gin.Default() 开始使用 Gin (默认情况下为所有路由启用日志记录和恢复)。但是有一条路由(即 /health )每 5 秒被 ping 一次。在不更改大部分代码的情况
gin 是目前 Go 里面使用最广泛的框架之一了,弄清楚 gin 框架的原理,有助于我们更好的使用 gin。这个系列 gin 源码阅读会逐步讲明白 gin 的原理,欢迎关注后续文章。 gin
我从 gin 文档中了解到,您可以将 json 绑定(bind)到类似 的结构 type Login struct { User string `form:"user" json:"u
我正在使用 API,GET 和 POST 工作正常,除非我尝试通过其 ID 获取选择记录(例如/articles/2)。文章存在,当通过/articles 路径检索所有记录时,我得到了正确的响应。这是
我找不到在 UNIX 中正确执行此代码的方法: package main import ( "time" "github.com/gin-gonic/gin" "net/http" ) t
我尝试使用作为 Golang 框架的 Gin。 https://github.com/gin-gonic/gin 我从官方github上复制了示例代码。 就像这样。 package main impo
下面访问gin-gonic服务器时,HTTP客户端应该收到code 500,却收到code 200。 package main import ( "github.com/gin-contrib
我使用 Guice/Gin 设计了一个新项目,因此我可以使我们的代码更加模块化和可交换,尤其是在测试时。 但是,我无法弄清楚如何在实践中完成这项工作。我的印象是我可以在我的测试中创建一个新的 Gin/
我正在尝试在 golang:alpine docker 镜像上运行一个非常简单的 go/gin 程序。这无法运行/构建。 运行容器: docker run -it --rm golang:1.10.1
本文介绍如何通过 rk-boot 快速搭建静态文件下载 Web 服务。什么是 静态文件下载 Web UI?通过配置文件,快速搭建可下载文件的 Web 服务。 请访问如下地址获取完整教程: r
这是我的一个例子 - public class GinDemoPresenter implements Presenter { private View view; @Inject
我正在尝试使用一种干净的方法,使用传递给我的类的父上下文来优雅地停止我的gin服务器。 这是我当前的代码 有没有更清洁的方法可以做到这一点?感觉像很多样板代码和不必要的例如使用无限循环完成如此简单的任
我有以下代码 public class AppGinModule extends AbstractGinModule{ @Override protected void configu
我正在使用OPTIONS方法获得204,但是似乎没有碰到终点 只需构建一个简单的文件上传端点,如下所示: package main import ( "cloud.google.com/go
在对其数据执行验证后,我试图用它的数据恢复上下文。我需要数据在下一个函数中根据需要继续移动。 我是 golang 的新手,下面的代码是我所能做的。非常感谢任何帮助和更好的方法。 提前致谢。 验证中间件
有一个使用gin-gonic框架以golang编写的服务。 我只想将application/json支持为mime类型,并且如果它始终以UTF-8格式运行,那就太好了。如果服务的业务逻辑将获得不同编码
我试图在我的 Handler 上进行一些处理后传递一些变量功能。我该怎么办 redirect到一个新页面并将一些 json 变量传递给这个新模板? // main package func main(
我运行关于文件上传的 gin 示例,这个 repo 来自 https://github.com/gin-gonic/examples/tree/5898505356e9064c49abb075eae8
我收到以下错误消息: controllers/user.go:4:2: cannot find package "(underscore)/home/ubuntu/goapi/src/github.c
我需要在中间件函数中操作响应数据。假设我有产品处理程序和客户处理程序。产品处理程序返回产品列表,客户返回客户列表。在中间件函数中,我想将这些响应转换为 ApiResponse 结构。 type Api
我是一名优秀的程序员,十分优秀!