ASP.Net MVC 5如何加密JWT令牌



我已经发布了一些关于在ASP中使用JWT的帖子。. Net MVC,它指导如何发出和使用签名JSON Web令牌。

如果我们需要在JWT有效负载中传输一些敏感数据,谁能指导如何根据JSON Web加密(JWE)规范发布和使用加密的JWT ?

理解JWT

JSON Web令牌(JWT)是一种紧凑的url安全方式,用于表示要在双方之间传输的声明。JWT中的声明被编码为JavaScript对象表示法(JSON)对象,该对象用作JSON Web签名(JWS)结构的有效载荷或JSON Web加密(JWE)结构的明文,使声明能够进行数字签名或MACed和/或加密。

JWT什么?
https://jwt.io/introduction/

Json Web令牌标准
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-25

JWT解剖
https://scotch.io/tutorials/the-anatomy-of-a-json-web-token

用JavaScript创建JSON Web令牌
https://www.jonathan-petitcolas.com/2014/11/27/creating-json-web-token-in-javascript.html

现在,我们了解了JWT调用以及如何从服务器端提供服务。这里我有一个HTML页面,我有按钮,也设置了一些自定义参数。

    <script src="//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js"></script>
    <script language="JavaScript" type="text/javascript" src="https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js"></script>
<script type="text/javascript">
    $(function () {
        $("#btnJWTApi").click(function () {
                    // Defining our token parts
                    // You can use one of these, as alg
                    // HS256, HS386, HS512
                    // Always keep type as JWT
                    var header = {
                        "alg": "HS256",
                        "typ": "JWT"
                    };
    
                    var tNow = KJUR.jws.IntDate.getNow();
                    var tEnd = KJUR.jws.IntDate.getNow() + 60 * 5;
                    // dynamically pass these data using a function
                    var data = {
                        "appId": "yourAppId",
                        "iat": tNow,
                        // iat (issued at time) should be set to time when request has been generated
                        "exp": tEnd,
                        // exp (expiration) should not be more than 5 minutes from now, this is to prevent Replay Attacks
                        "method": "TestMethod",
                        "Q": "test",
                        "SecretKey": "MySecretKey"
                    };
                    // Secret key is used for calculating and verifying the signature.
                    // The secret signing key MUST only be accessible by the issuer and the User,
                    // it should not be accessible outside of these two parties.                
                    // Use the Secret you set during user registration from the Plugin
                    var secret = btoa('MySecret ');
    
                    function base64url(source) {
                        // Encode in classical base64
                        encodedSource = CryptoJS.enc.Base64.stringify(source);
                        // Remove padding equal characters
                        encodedSource = encodedSource.replace(/=+$/, '');
                        // Replace characters according to base64url specifications
                        encodedSource = encodedSource.replace(/+/g, '-');
                        encodedSource = encodedSource.replace(///g, '_');
                        return encodedSource;
                    }
    
                    var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
                    var encodedHeader = base64url(stringifiedHeader);
    
                    var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
                    var encodedData = base64url(stringifiedData);
    
                    var signature = encodedHeader + "." + encodedData;
                    signature = CryptoJS.HmacSHA256(signature, secret);
                    signature = base64url(signature);
    
                    var targetEle = $("#data");
                    $.ajax(
                        {
                            type: "POST",
                            url: "http://localhost:12345/api/v1/MyController/SecureMethod",        
                            data: '{"token":"' + encodedHeader + "." + encodedData + "." + signature + '"}',
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",
                            success: function (data) {
                                targetEle.html("<pre>" + JSON.stringify(data, null, 't') + "</pre>");
                            },
                            error: function () {
                                alert('error');
                            }
                        });
                });        
            });
    </script>

此调用将生成加密令牌,其中包括appId,secret和方法名称的有效负载数据。

(这里创建一个通用方法,首先调用,然后根据在令牌中传递的数据调用进一步的方法)

这将调用你的方法SecureMethod而不是直接调用TestMethod。并解密令牌。

public string SecureMethod(dynamic tokenObject)
{
    //save at a time of user registration. 
    string applicationID = appSecret get from database;
    string secretKey = appSecret get from database;
}
var bytes = Encoding.UTF8.GetBytes(secretKey);
                    var secret = Convert.ToBase64String(bytes);
                    var jwtDecryption = JsonWebToken.DecodeToObject(token, secret, true, true);
                    var jsonObj = JObject.FromObject(jwtDecryption);
                    string appId = jsonObj["appId"].Value<string>();
 if (appId.Equals(applicationID)
 {
      object restService = new MyController();
  var method = restService.GetType().GetMethod(jsonObj["method"].ToString(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 }
 if (method != null)
 {    
  var parameters = method.GetParameters().Select(p => Convert.ChangeType(jsonObj[p.Name].ToString(), p.ParameterType)).ToArray();
 object response = method.Invoke(restService, parameters); //your actual method should  
 return new JavaScriptSerializer().Serialize(response);
 }

method.Invoke(restService, parameters);将有方法名和参数,所以它会调用你的方法并传递参数。

public IHttpActionResult TestMethod([FromBody]Response model)
{
   // you will get parameters in a model 
  return Ok();
}

欢迎任何建议!

最新更新