使JWT编码更快

8

我有一个使用password授权的/token接口。由于它要编码一个JWT令牌,因此延迟高达1秒。有没有办法让签署JWT更快?

我正在使用 Go 语言和 github.com/dgrijalva/jwt-go 库。

package main

import (
    "crypto/rsa"
    "git.snappfood.ir/golang/framework/assert"
    "io/ioutil"
    "time"

    
    "github.com/dgrijalva/jwt-go"
    "github.com/sirupsen/logrus"
)

var (
    private *rsa.PrivateKey
    public  *rsa.PublicKey
)

func main() {
    var err error
    var priv, pub []byte
    pub, err = ioutil.ReadFile("public.pem")
    if err!=nil{
        panic(err)
    }
    priv, err = ioutil.ReadFile("private.pem")
    if err!=nil{
        panic(err)
    }

    public, err = jwt.ParseRSAPublicKeyFromPEM(pub)
    if err!=nil{
        panic(err)
    }

    private, err = jwt.ParseRSAPrivateKeyFromPEM(priv)
    if err!=nil{
        panic(err)
    }

    data := map[string]interface{}{
        "jti": "dara",
        "scopes": func() []string {
            return []string{"sara", "dara"}
        }(),
        "aud": "aud",
        "sub": "",
    }
    cl := jwt.MapClaims{}

    for k, v := range data {
        cl[k] = v
    }
    cl["iat"] = time.Now().Add(-6 * time.Hour).Unix()
    cl["exp"] = time.Now().UTC().Add(1 * time.Hour).Unix()

    t := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), cl)

    t2 := time.Now()
    tokenString, err := t.SignedString(private)
    assert.Nil(err)
    logrus.Warn(time.Since(t2))
    logrus.Warn(tokenString)

}

6
在您的情况下,SignedString简化为调用rsa.SignPKCS1v15。该函数的时间语义由其第一个参数——rand.Reader控制。在jwt-go的情况下,这个参数是crypto/rand.Readercrypto/rand.Reader的实现取决于您的平台。由于系统熵值低,它可能会阻塞很长时间。尝试在不同平台上测量。 - thwd
感谢您的描述@thwd。我正在使用Ubuntu服务器,想要减少编码时间,如何增加熵?还是有其他方法吗? - slifer2015
3
你是怎么得出 JWT 生成需要 1 秒的结论的?这听起来对我来说非常不可能。你在分析中看到 JWT 编码占用了大部分时间吗? - Song Gao
1
我无法确定为什么它需要1秒钟,这真的很慢。我还在项目中签署JWT,但没有可衡量的影响。作为提示,您使用的库github.com/dgrijalva/jwt-go已归档且不再维护。我建议切换到https://github.com/golang-jwt/jwt,即使这可能不会影响您的问题。 - fabs
2个回答

3

不需要深入了解库的细节,它很小但你不需要初始化一个map[string]interface然后循环遍历它来填充一个jwt.MapClaims{}。你可以像这样直接从jwt.MapClaims{}开始:

cl := jwt.MapClaims{
    "jti": "dara",
    "scopes": func() []string {
        return []string{"sara", "dara"}
    }(),
    "aud": "aud",
    "sub": "",
    // no need to do these separately:
    "iat": time.Now().Add(-6 * time.Hour).Unix(),
    "exp": time.Now().UTC().Add(1 * time.Hour).Unix(),
}

考虑使用基准测试来尝试不同的方法。


编辑:

我认为time.Now()有时可能会很慢,这取决于机器/操作系统,并且可能是一个可能的因素。因此,请确保对time.Now()进行基准测试,并查找诸如this之类的问题,如果您想深入了解。


-2
在Golang中,您可以随时降至C级别。但是这也增加了运输应用程序的复杂性。但如果任何毫秒都很重要,那么这可能是出路。
但与此同时(我还没有对任何东西进行过分析),它仍然是Go语言。您可以轻松地并行化私人/公共ParseRSAPrivateKeyFromPEM调用,以节省几个毫秒。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接