0

我已经发布了几篇关于在 ASP.Net MVC 中使用 JWT 的帖子,这些帖子指导了如何发布和使用 Signed JSON Web Tokens。

任何人都可以指导如何按照 JSON Web 加密 (JWE) 规范发布和使用加密的 JWT,以防我们需要在 JWT 有效负载中传输一些敏感数据。

4

1 回答 1

2

了解智威汤逊

JSON Web Token (JWT) 是一种紧凑的 URL 安全方式,用于表示要在两方之间传输的声明。JWT 中的声明被编码为 JavaScript 对象表示法 (JSON) 对象,该对象用作 JSON Web 签名 (JWS) 结构的负载或 JSON Web 加密 (JWE) 结构的明文,从而使声明成为数字签名或 MACed 和/或加密。

什么智威汤逊?
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();
}

欢迎任何建议!

于 2016-09-12T10:18:52.127 回答