jaswang 发表于 2022-4-1 17:24:39

基于cookire双向加密

# go 基于cookie的双向加密验证
标签: gocookie 双向加密



>**cookie 双向加密验证**

```
//高级加密标准 (aes)
16,24,32位字符串的话,分别对应AES-128,AES-192,AES-256 加密方法
//16,24,32位字符串的话,分别对应AES-128,AES-192,AES-256 加密方法
//key不能泄露
var PwdKey = []byte("DIS**#KKKDJJSKDI")

// PKCS7Padding PKCS7 填充模式
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
        padding := blockSize - len(ciphertext)%blockSize
        //Repeat()函数的功能是把切片[]byte{byte(padding)}复制padding个,然后合并成新的字节切片返回
        padtext := bytes.Repeat([]byte{byte(padding)}, padding)
        return append(ciphertext, padtext...)
}

// PKCS7UnPadding 填充的反向操作,删除填充字符串
func PKCS7UnPadding(origData []byte) ([]byte, error) {
        //获取数据长度
        length := len(origData)
        if length == 0 {
                return nil, errors.New("加密字符串错误!")
        } else {
                //获取填充字符串长度
                unpadding := int(origData)
                //截取切片,删除填充字节,并且返回明文
                return origData[:(length - unpadding)], nil
        }
}

// AesEcrypt 实现加密
func AesEcrypt(origData []byte, key []byte) ([]byte, error) {
        //创建加密算法实例
        block, err := aes.NewCipher(key)
        if err != nil {
                return nil, err
        }
        //获取块的大小
        blockSize := block.BlockSize()
        //对数据进行填充,让数据长度满足需求
        origData = PKCS7Padding(origData, blockSize)
        //采用AES加密方法中CBC加密模式
        blocMode := cipher.NewCBCEncrypter(block, key[:blockSize])
        crypted := make([]byte, len(origData))
        //执行加密
        blocMode.CryptBlocks(crypted, origData)
        return crypted, nil
}

// AesDeCrypt 实现解密
func AesDeCrypt(cypted []byte, key []byte) ([]byte, error) {
        //创建加密算法实例
        block, err := aes.NewCipher(key)
        if err != nil {
                return nil, err
        }
        //获取块大小
        blockSize := block.BlockSize()
        //创建加密客户端实例
        blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
        origData := make([]byte, len(cypted))
        //这个函数也可以用来解密
        blockMode.CryptBlocks(origData, cypted)
        //去除填充字符串
        origData, err = PKCS7UnPadding(origData)
        if err != nil {
                return nil, err
        }
        return origData, err
}

//加密base64
func EnPwdCode(pwd []byte) (string, error) {
        result, err := AesEcrypt(pwd, PwdKey)
        if err != nil {
                return "", err
        }
        return base64.StdEncoding.EncodeToString(result), err
}

//解密
func DePwdCode(pwd string) ([]byte, error) {
        //解密base64字符串
        pwdByte, err := base64.StdEncoding.DecodeString(pwd)
        if err != nil {
                return nil, err
        }
        //执行AES解密
        return AesDeCrypt(pwdByte, PwdKey)

}


```

>go 拦截器

```
package help

import "net/http"

// FilterHandle 声明一个新的数据类型
type FilterHandle func(rw http.ResponseWriter, r *http.Request) error

// Filter 拦截器结构体
type Filter struct {
        //用来存需要拦截的url
        filterMap mapFilterHandle
}

//初始化
func NewFilter() *Filter {
        return &Filter{
                filterMap: make(mapFilterHandle),
        }
}

// RegisterFilterUri 注册拦截器
func (f *Filter) RegisterFilterUri(uri string, handler FilterHandle) {
        f.filterMap = handler
}

// GetFilterHandle 获取拦截器
func (f *Filter) GetFilterHandle(uri string) FilterHandle {
        return f.filterMap
}

type WebHandle func(rw http.ResponseWriter, r *http.Request)

func (f *Filter) Handle(webHandle WebHandle) func(rw http.ResponseWriter, r *http.Request) {
        return func(rw http.ResponseWriter, r *http.Request) {
                for path, handle := range f.filterMap {
                        if path == r.RequestURI {
                                err := handle(rw, r)
                                if err != nil {
                                        rw.Write([]byte(err.Error()))
                                        return
                                }
                                break
                        }

                }
                //执行正常注册的函数
                webHandle(rw, r)
        }
}
```
>实现拦截器
```
package main

import (
        "errors"
        "fmt"
        "net/http"
        "order/encrypt"
        "order/help"
)

func Check(rw http.ResponseWriter, r *http.Request) {
        fmt.Println("Check")
}
func Auth(rw http.ResponseWriter, r *http.Request) error {
        //添加基于cookie的权限验证
        err := CheckUserInfo(r)
        if err != nil {
                return err
        }
        return nil
}

//检查用户信息
func CheckUserInfo(r *http.Request) error {
        uidCookie, err := r.Cookie("uid")
        if err != nil {
                return errors.New("用户UID cookie 获取失败")
        }
        signCookie, err := r.Cookie("sign")
        if err != nil {
                return errors.New("用户加密cookie 获取失败")
        }
        //对加密信息进行解密
        signByte, err := encrypt.DePwdCode(signCookie.Value)
        fmt.Println("sign加密串", string(signByte))
        fmt.Println("uid", uidCookie.Value)
        ok := CheckCookie(uidCookie.Value, string(signByte))
        if !ok {
                return errors.New("身份校验失败")
        }
        return nil
}

//检查cookie是否一致
func CheckCookie(checkStr string, signStr string) bool {
        if checkStr == signStr {
                return true
        }
        return false
}
func main() {
        filter := help.NewFilter()
        filter.RegisterFilterUri("/check", Auth)
        http.HandleFunc("/check", filter.Handle(Check))
        http.ListenAndServe(":9999", nil)
}
```


页: [1]
查看完整版本: 基于cookire双向加密