美文网首页
jwt 用rsa公钥私钥进行验证(python发送,java接受

jwt 用rsa公钥私钥进行验证(python发送,java接受

作者: 王剑_a9e1 | 来源:发表于2018-05-15 11:12 被阅读0次

JWT的主要应用场景

身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。 信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

JWT的结构

JWT包含了使用.分隔的三部分: Header 头部 Payload 负载 Signature 签名

其结构看起来是这样的Header.Payload.Signature

Header

在header中通常包含了两部分:token类型和采用的加密算法。{ "alg": "HS256", "typ": "JWT"} 接下来对这部分内容使用 Base64Url 编码组成了JWT结构的第一部分。

Payload

Token的第二部分是负载,它包含了claim, Claim是一些实体(通常指的用户)的状态和额外的元数据,有三种类型的claim:reserved, publicprivate.Reserved claims: 这些claim是JWT预先定义的,在JWT中并不会强制使用它们,而是推荐使用,常用的有 iss(签发者),exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间)。 Public claims:根据需要定义自己的字段,注意应该避免冲突 Private claims:这些是自定义的字段,可以用来在双方之间交换信息 负载使用的例子:{ "sub": "1234567890", "name": "John Doe", "admin": true} 上述的负载需要经过Base64Url编码后作为JWT结构的第二部分。

Signature

创建签名需要使用编码后的header和payload以及一个秘钥,使用header中指定签名算法进行签名。例如如果希望使用HMAC SHA256算法,那么签名应该使用下列方式创建: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 签名用于验证消息的发送者以及消息是没有经过篡改的。 完整的JWT 完整的JWT格式的输出是以. 分隔的三段Base64编码,与SAML等基于XML的标准相比,JWT在HTTP和HTML环境中更容易传递。 下列的JWT展示了一个完整的JWT格式,它拼接了之前的Header, Payload以及秘钥签名:


encoded-jwt3.png

python发送数据

import calendar
import datetime
import time
import jenkins
import requests
import json
import logging
import configparser
import jwt

#read the private_key 
with open('rsa_private_key.pem') as f:
    private_key = f.read()
exp = datetime.datetime.utcnow() + datetime.timedelta(minutes=10)
exp = calendar.timegm(exp.timetuple())
# Generate the JWT
payload = {
    # issued at time
    'iat': int(time.time()),
    # JWT expiration time (10 minute maximum)
    'exp': exp,
    # Integration's GitHub identifier
    'iss': 'tom',
}

encoded = jwt.encode(payload, private_key, algorithm='RS256')
try:
    headers = {
        'content-type': "application/json",
        'jwt': encoded
    }
    response = requests.post(server_url, headers=headers)
    if response.status_code != 200:
        logger.error("commit builds post go wrong , status code is : {}".format(response.status_code))
        logger.error(response.text)
except Exception as e:
        logger.error("commit builds post Error: {}".format(e))

java接受数据(springboot拦截器)

public class WebInterceptor implements HandlerInterceptor {
    static final Logger logger = LoggerFactory.getLogger(WebInterceptor.class);

    @Autowired
    private MyConfig myconfig;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        logger.info("==============  request before  ==============");
        String jwt = httpServletRequest.getHeader("jwt");
        logger.info("jwt is : " + jwt);
        String str = null;
        if(myconfig == null){
            WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(httpServletRequest.getServletContext());
            myconfig = wac.getBean(MyConfig.class);
        }

       
        try {
             //read the public key
            File file = ResourceUtils.getFile(myconfig.getRsaPublicKeyDir());
            FileReader reader = new FileReader(file);
            BufferedReader bReader = new BufferedReader(reader);
            StringBuilder sb = new StringBuilder();
            String s;
            while ((s = bReader.readLine()) != null) {
                sb.append(s);
            }
            bReader.close();
            str = sb.toString();

            RsaKeyUtil rsaKeyUtil = new RsaKeyUtil();
            PublicKey publicKey = rsaKeyUtil.fromPemEncoded(str);

            // create a JWT consumer
            JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                    .setRequireExpirationTime()
                    .setVerificationKey(publicKey)
                     //不能少不然会报错
                    .setRelaxVerificationKeyValidation()
                    .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
                            new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, // which is only RS256 here
                                    AlgorithmIdentifiers.RSA_USING_SHA256))

                    .build();

            // validate and decode the jwt
            JwtClaims jwtDecoded = jwtConsumer.processToClaims(jwt);
            Map<String, Object> jwtClaims = jwtDecoded.getClaimsMap();
            Object iss = jwtClaims.get("iss");

            logger.info("jwtClaims is : "+ jwtClaims);
        }catch (Exception e){
            logger.error(e.getMessage());
            return false;
        }

        return true;
    }

}

签名的目的

最后一步签名的过程,实际上是对头部以及载荷内容进行签名。一般而言,加密算法对于不同的输入产生的输出总是不一样的。对于两个不同的输入,产生同样的输出的概率极其地小(有可能比我成世界首富的概率还小)。所以,我们就把“不一样的输入产生不一样的输出”当做必然事件来看待吧。

所以,如果有人对头部以及载荷的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的。

image

服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。那么服务器应用是怎么知道我们用的是哪一种算法呢?别忘了,我们在JWT的头部中已经用alg字段指明了我们的加密算法了。

如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。

信息会暴露?

是的。

所以,在JWT中,不应该在载荷里面加入任何敏感的数据。在上面的例子中,我们传输的是用户的User ID。这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。

但是像密码这样的内容就不能被放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。

JWT的适用场景

我们可以看到,JWT适合用于向Web应用传递一些非敏感信息。例如在上面提到的完成加好友的操作,还有诸如下订单的操作等等。

其实JWT还经常用于设计用户认证和授权系统,甚至实现Web应用的单点登录。在下一次的文章中,我将为大家系统地总结JWT在用户认证和授权上的应用。

相关文章

  • jwt 用rsa公钥私钥进行验证(python发送,java接受

    JWT的主要应用场景 身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身...

  • 加密相关

    公钥加密 私钥解密 ,私钥加密,公钥验证(签名) HTTPS -- AFSecurityPolicy RSA ...

  • RSA SHA256 非对称签名与验证 sign verify

    RSA主要用法 公钥加密(encrypt),私钥解密(decrypt) 私钥签名(sign),公钥验证(verif...

  • RSA非对称加密算法

    RSA算法,经典非对称加密算法,通过生成公钥 私钥 进行加密解密 公钥加密 私钥解密 反之 私钥加密 公钥...

  • ssh

    --对外公布的是公钥 --有公钥的外面人,使用公钥进行解密,同时使用公钥进行加密发送 --自己用私钥加密发送。同时...

  • Java RSA加密/解密

    Java RSA加密&解密如下: 拿到RSA 公钥和私钥后我们可以保存到文件中,代码如下: 解析已有的公钥和私钥,...

  • 加密解密 签名验签学习

    基本概念: 加密:发送方利用接受方的公钥对要发送的明文进行加密。 解密:接收方利用自己的私钥进行解密。 公钥与私钥...

  • 加密

    哈希,md5 RSA 公钥加密私钥解密,私钥加密公钥解密 数据大,效率低,银行等用

  • python学习二(http请求+rsa签名)

    背景: rsa签名/验名 公钥私钥文件 公钥和私钥获取不进行细致描述,网络有较多资料,本文提供一对公钥和私钥。需要...

  • iOS本地生成RSA密钥字符串

    前言 最近公司的项目要使用RSA加密的方式,需要客户端本地生成公钥和私钥,将公钥发送给服务器,服务器使用公钥进行...

网友评论

      本文标题:jwt 用rsa公钥私钥进行验证(python发送,java接受

      本文链接:https://www.haomeiwen.com/subject/jwsedftx.html