Fabric区块链浏览器(2)

这篇具有很好参考价值的文章主要介绍了Fabric区块链浏览器(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文是区块链浏览器系列的第四篇。

在上一篇文章介绍如何解析区块数据时,使用session对客户端上传的pb文件进行区分,到期后自动删除。

在这片文章中,会着重介绍下认证系统的实现,主要分为三部分:

  • 添加数据库,存储用户信息
  • 实现用户认证中间件
  • 修改路由

1. 用户信息存储

我这里使用MySQL来存储数据,使用gorm来实现与数据库的交换。

首先需要创建用户表:

CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` longtext,
  `created_at` datetime(3) DEFAULT NULL,
  `updated_at` datetime(3) DEFAULT NULL,
  `deleted_at` datetime(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

创建MySQL链接句柄:

func InitDB(source string) (*gorm.DB, error) {
	dblog := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags),
		logger.Config{
			LogLevel:                  logger.Error,
			IgnoreRecordNotFoundError: true,
			Colorful:                  true,
			SlowThreshold:             time.Second,
		},
	)
	return gorm.Open(mysql.Open(source), &gorm.Config{
		SkipDefaultTransaction:                   true,
		AllowGlobalUpdate:                        false,
		DisableForeignKeyConstraintWhenMigrating: true,
		Logger:                                   dblog,
	})
}

表结构比较简单,实现两个查询接口:

func GetUserByName(name string) (*User, error) {
	var user User
	db.Get().First(&user, "name = ?", name)
	if user.ID == 0 {
		return nil, fmt.Errorf("user with name: %s is not found", name)
	}
	return &user, nil
}

func GetUserByID(id uint) (*User, error) {
	var user User
	db.Get().First(&user, "id = ?", id)
	if user.ID == 0 {
		return nil, fmt.Errorf("user with id: %d is not found", id)
	}
	return &user, nil
}

除了查询接口外,还需要提供用户注册,这里直接使用Save()接口进行数据库写入操作:

func RegisterUser(name, password string) (*LoginResponse, error) {
	salt := genSalt()
	u := &User{
		Name:     name,
		Password: utils.CalcPassword(password, salt),
		Salt:     salt,
	}
	if err := db.Get().Save(u).Error; err != nil {
		return nil, errors.Wrap(err, "RegisterUser error")
	}

	now := time.Now()
	claims := &jwtv5.RegisteredClaims{
		ExpiresAt: jwtv5.NewNumericDate(now.Add(30 * time.Minute)),
		Issuer:    "browser",
		Subject:   fmt.Sprintf("%d", u.ID),
	}
	token := jwtv5.NewWithClaims(jwtv5.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(securityKey)
	if err != nil {
		return nil, errors.Wrap(err, "create token error")
	}

	return &LoginResponse{
		Token:    tokenString,
		Expire:   now.Add(30 * time.Minute).Unix(),
		ID:       u.ID,
		Username: u.Name,
	}, nil
}

用户认证采用的JWT(JSON Web Token),实现方法在JWT介绍有介绍,所以还需要提供两个接口:Login实现token获取,RefreshToken刷新token:

func Login(name, password string) (*LoginResponse, error) {
	user, err := GetUserByName(name)
	if err != nil {
		return nil, errors.Wrap(err, "GetUserByName error")
	}

	if utils.CalcPassword(password, user.Salt) != user.Password {
		return nil, errors.New("user name or password is incorrect")
	}

	now := time.Now()
	claims := &jwtv5.RegisteredClaims{
		ExpiresAt: jwtv5.NewNumericDate(now.Add(30 * time.Minute)),
		Issuer:    "browser",
		Subject:   fmt.Sprintf("%d", user.ID),
	}
	token := jwtv5.NewWithClaims(jwtv5.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(securityKey)
	if err != nil {
		return nil, errors.Wrap(err, "create token error")
	}

	return &LoginResponse{
		Token:    tokenString,
		Expire:   now.Add(30 * time.Minute).Unix(),
		ID:       user.ID,
		Username: user.Name,
	}, nil
}

func RefreshToken(id uint) (*LoginResponse, error) {
	user, err := GetUserByID(id)
	if err != nil {
		return nil, errors.Wrap(err, "GetUserByName error")
	}

	now := time.Now()
	claims := &jwtv5.RegisteredClaims{
		ExpiresAt: jwtv5.NewNumericDate(now.Add(30 * time.Minute)),
		Issuer:    "browser",
		Subject:   fmt.Sprintf("%d", user.ID),
	}
	token := jwtv5.NewWithClaims(jwtv5.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(securityKey)
	if err != nil {
		return nil, errors.Wrap(err, "create token error")
	}
	return &LoginResponse{
		Token:    tokenString,
		Expire:   now.Add(30 * time.Minute).Unix(),
		ID:       user.ID,
		Username: user.Name,
	}, nil
}

2. 用户认证中间件

关于Gin中间件的开发,可以参照gin中间件开发,这里增加三种认证方式:noAuth,不使用认证;basicAuth,用户名密码方式认证;tokenAuth,使用token进行认证:

func noAuth(ctx *gin.Context) {
	ctx.Next()
}

func basicAuth(ctx *gin.Context) {
	name, pwd, ok := ctx.Request.BasicAuth()
	if !ok {
		srvLogger.Error("basic auth failed")
		ctx.JSON(http.StatusForbidden, gin.H{"code": http.StatusForbidden, "msg": "basic auth failed"})
		ctx.Abort()
		return
	}
	user, err := data.GetUserByName(name)
	if err != nil {
		srvLogger.Errorf("GetUserByName error: %s", err.Error())
		ctx.JSON(http.StatusForbidden, gin.H{"code": http.StatusForbidden, "msg": err.Error()})
		ctx.Abort()
		return
	}
	if utils.CalcPassword(pwd, user.Salt) != user.Password {
		srvLogger.Error("user name or password is incorrect")
		ctx.JSON(http.StatusForbidden, gin.H{"code": http.StatusForbidden, "msg": "user name or password is incorrect"})
		ctx.Abort()
		return
	}
	ctx.Next()
}

func tokenAuth(ctx *gin.Context) {
	if err := data.ParseJWT(strings.Split(ctx.Request.Header.Get("Authorization"), " ")[1]); err != nil {
		srvLogger.Errorf("tokenAuth error: %s", err.Error())
		ctx.JSON(http.StatusForbidden, gin.H{"code": http.StatusForbidden, "msg": "token auth failed"})
		ctx.Abort()
		return
	}
	ctx.Next()
}

3. 注册路由

在上篇中,注册的路由是这样的:

engine.POST("/login", login)
engine.GET("/hi/:name", sayHi)
engine.POST("/block/upload", upload)
engine.GET("/block/parse/:msgType", parse)
engine.POST("/block/update/:channel", updateConfig)

现在需要对/block/upload/block/parse/:msgType/block/update/:channel接口增加认证,这就需要用到我们上面实现的三个中间件。

由于中间件会按照它们的注册顺利来执行,所以需要认证中间件需要在相应的处理接口前执行,针对noAuth的情况,上面的代码并不需要进行修改,但对于basicAuthtokenAuth,上面的代码就需要修改了:

engine.POST("/block/upload", basicAuth, upload)
engine.GET("/block/parse/:msgType", basicAuth, parse)
engine.POST("/block/update/:channel", basicAuth, updateConfig)

engine.POST("/block/upload", tokenAuth, upload)
engine.GET("/block/parse/:msgType", tokenAuth, parse)
engine.POST("/block/update/:channel", tokenAuth, updateConfig)

当然我们也可以使用Handle(httpMethod, relativePath string, handlers ...HandlerFunc)来进行路由注册:

for _, router := range server.Routers() {
	var handlers []gin.HandlerFunc
	if router.AuthType == 0 {
		router.AuthType = conf.AuthType
	}
	switch router.AuthType {
	case config.Server_BASICAUTH:
		handlers = append(handlers, basicAuth)
	case config.Server_TOKENAUTH:
		handlers = append(handlers, tokenAuth)
	default:
		handlers = append(handlers, noAuth)
	}
	handlers = append(handlers, router.Handler)
	engine.Handle(router.Method, router.Path, handlers...)
}

项目完整代码可以从Github上查看。


Fabric区块链浏览器(2)

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意文章来源地址https://www.toymoban.com/news/detail-664046.html


到了这里,关于Fabric区块链浏览器(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (Fabric学习八)部署区块链浏览器Hyperledger explorer

    区块链浏览器Hyperledger explorer: 区块链浏览器:官方网站https://github.com/hyperledger-labs/blockchain-explorer 可以看到他需要以下几个文件 : docker-compose.yaml test-network.json config.json 注意:如果从来没有设置过postgreSQL,那最好使用默认的账号hppoc和密码password,不然会报role \\\'你自己的定

    2024年02月09日
    浏览(27)
  • 区块链——Hyperledger Fabric2.2多机搭建及区块链浏览器

    1、设置网络 2、安装docker和docker-compose 3、安装golang环境 1、编写证书文件 2、生成证书文件 3、复制证书文件到节点 1、编写创世块文件 2、生成创世块文件和通道文件 1、生成创世区块 2、生成通道文件 3、为 Org1 定义锚节点 4、为 Org2 定义锚节点 5、将生成的文件拷贝到另两台

    2024年02月11日
    浏览(20)
  • Fabric 超级账本学习【5】Fabric2.4网络环境下——搭建Hyperledger Fabric区块链浏览器

    博主最近在搭建Hyperledger Fabric区块链浏览器过程中也学习了很多博主的搭建流程,踩了很多雷,踩了很多 坑,现将成功搭建好的Hyperledger Fabric区块链浏览器详细流程分享如下,帮助大家避雷闭坑 Hyperledger Explorer 是一个简单,强大,易于使用,维护良好的开源实用程序,可浏

    2023年04月23日
    浏览(28)
  • hyperledger fabric2.4.0基础搭建到区块链浏览器搭建

    基础环境借鉴  如下博客地址安装成功Ubuntu20.04下安装fabric2.4环境 从零开始超详细步骤【亲测有效】及Hyperledger Explorer安装_小草cys的博客-CSDN博客_ubuntu安装fabricq 区块链浏览器借鉴如下博客配置成功 2021-05-02-fabric浏览器搭建_Soulmate_666的博客-CSDN博客_搭建fabric浏览器 config.json

    2024年02月11日
    浏览(20)
  • hyperledger fabric explorer 超级账本区块链浏览器搭建-docker的方式

    hyperledger fabric explorer 超级账本区块链浏览器搭建-使用docker的方式快速搭建一个超级账本区块链浏览器 区块链浏览器可以让用户更加直观地查看当前超级账本网络的情况,来观察整个区块链上的块数,节点数,通道,链码等; 官方推荐的搭建区块链浏览器有两种方法,一种是

    2023年04月08日
    浏览(18)
  • Hyperledger Fabric项目搭建区块链浏览器Hyperledger-blockchain-explorer

    区块链浏览器官网:https://github.com/hyperledger/blockchain-explorer 如果虚拟机没有联网,导致下载不下来,也可以前往Fabric-explorer附件下载进行下载,之后在本地根据需要修改,修改后上传到虚拟机 此时目录结构如下图所示 3.1修改test-network.json—— 网络配置文件,包含身份的指定

    2024年02月08日
    浏览(25)
  • 区块链浏览器

    区块链浏览器就是将区块链里面的信息,全部列出来到网站上 根本不需要资料,直接上实体网站即可,实在看不懂英文就翻译 BlockExplorer.com | Home Bitcoin - Open source P2P money Ethereum (ETH) Blockchain Explorer - etherchain.org - 2022 https://live.blockcypher.com/btc/

    2024年02月16日
    浏览(19)
  • 区块链浏览器与合约代码

    此文系:Vue3.0 +Quasar+ ethers.js 和以太坊智能合约交互 系列教程之一。 区块链浏览器 在本教程中,我一直在说区块链是去中心化的,它想打造的是一个数据永不可篡改且公开透明的数据世界。 那么这样的区块链它最重要的一环就是,需要一个简单易懂,普通用户就能随时查看

    2024年02月03日
    浏览(33)
  • 【区块链】HyperLedger Besu Alethio区块浏览器

    上一节我们已经完成了整个Besu区块链网络的搭建,本章将介绍通过Alethio区块链浏览器对上链数据进行查看和校验。同时,由于Besu区块链是可以通过EthSigner来实现带权限(token)访问的,那么在权限访问下还需要添加explorer-besu-plugin来实现,这个也会在本节中一并叙述。 Alet

    2024年03月19日
    浏览(17)
  • fisco区块链浏览器编译合约失败

    在fisco的区块链浏览器这个位置编译合约失败,但是合约可以正常执行,此时可能是因为浏览器在数据库中自动建表时,保存合约abi编码的字段长度不足的原因 将数据库中对应字段长度改长一些即可。 ps:这里编译的合约貌似必须在同一级目录下,多级目录合约无法检测到引

    2024年02月13日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包