前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Gin 框架之用户密码加密

Gin 框架之用户密码加密

作者头像
贾维斯Echo
发布2024-01-19 13:54:24
1450
发布2024-01-19 13:54:24
举报

一、引入

Gin是一个用Go语言编写的Web框架,而用户密码的加密通常是在应用程序中处理用户身份验证时的一个重要问题。

通常敏感信息你要防两类人:

  • 研发人员:包括你自己和你的同事。作为研发人员,你可能会接触到公司的敏感信息,如用户数据、商业机密等。
  • 攻击者:指那些有意获取或破坏敏感信息的人。他们可能是黑客、竞争对手、内部威胁等。

所以为了增加安全性,密码通常不应以明文形式存储在数据库中,而是应该经过适当的加密处理。

二、密码加密位置

实际上,你选择 servicerepositorydao,包括 domain 都可以:

  • service 加密:加密是一个业务概念,不是一个存储概念。
  • repository 加密:加密是一个存储概念,毕竟我们说的是“加密存储”。
  • dao 加密:加密是一个数据库概念,因为我完全可以选择利用数据库本身的加密功能来实现。
  • domain 加密:加密是一个业务概念,但是应该是“用户(User)”自己才知道怎么加密。

三、如何加密

加密算法的选择会直接影响你整个系统的安全性,因为攻击者一旦拿到了密码,差不多就可以为所欲为了。

选择加密算法的标准就一个,难破解。你要考虑以下问题:

  • 相同的密码,加密后的结果应该不同。你可以预期,很多用户习惯用 123456 这种密码,但是我们希望数据库存储的值还是不一样。
  • 难以通过碰撞、彩虹表来破解。

常见的加密算法无非就是下面这些,安全性逐步提高:

  1. md5 之类的哈希算法。
  2. 在 1 的基础上,引入了盐值(salt),或者进行多次哈希等。
  3. PBKDF2BCrypt 这一类随机盐值的加密算法,同样的文本加密后的结果都不同。

四、bcrypt 库加密

4.1 介绍

在Go语言中,可以使用bcrypt库来对密码进行安全加密,号称最安全的加密算法。

4.2 优点:

  • 不需要你自己去生成盐值。
  • 不需要额外存储盐值。
  • 可以通过控制 cost 来控制加密性能。
  • 同样的文本,加密后的结果不同。

4.3 使用

首先,你需要在Go中安装bcrypt库:

代码语言:javascript
复制
go get golang.org/x/crypto/bcrypt

下面是一个使用bcrypt库在对用户密码进行加密的示例:

代码语言:javascript
复制
package main

import (
	"fmt"
	"golang.org/x/crypto/bcrypt"
)

func main() {
	// 用户注册时使用的密码
	password := "user_password"

	// 使用bcrypt库对密码进行哈希处理
	hashedPassword, err := hashPassword(password)
	if err != nil {
		fmt.Println("Error hashing password:", err)
		return
	}

	fmt.Println("Original Password:", password)
	fmt.Println("Hashed Password:", hashedPassword)

	// 模拟用户登录时的密码验证
	err = comparePasswords(hashedPassword, "wrong_password")
	if err != nil {
		fmt.Println("Password does not match:", err)
	} else {
		fmt.Println("Password matches!")
	}

	err = comparePasswords(hashedPassword, "user_password")
	if err != nil {
		fmt.Println("Password does not match:", err)
	} else {
		fmt.Println("Password matches!")
	}
}

func hashPassword(password string) (string, error) {
	// 使用bcrypt库的GenerateFromPassword函数进行哈希处理
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}
	return string(hashedPassword), nil
}

func comparePasswords(hashedPassword, inputPassword string) error {
	// 使用bcrypt库的CompareHashAndPassword函数比较密码
	err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(inputPassword))
	return err
}

加密后的结果如下:

五、小黄书密码加密实践

webook/internal/service/user.go:

代码语言:javascript
复制
func (svc *UserService) SignUp(ctx context.Context, u domain.User) error {
	// 先加密密码
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(hash)
	// 然后存起来
	return svc.repo.Create(ctx, u)
}

func (svc *UserService) Login(ctx context.Context, email, password string) (domain.User, error) {
	// 先找用户
	u, err := svc.repo.FindByEmail(ctx, email)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}
	// 比较密码了
	err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	if err != nil {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	return u, nil
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引入
  • 二、密码加密位置
  • 三、如何加密
  • 四、bcrypt 库加密
    • 4.1 介绍
      • 4.2 优点:
        • 4.3 使用
        • 五、小黄书密码加密实践
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档