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

时间:2016-09-08 22:43:21

标签: asp.net asp.net-mvc asp.net-web-api2 jwt thinktecture

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

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

1 个答案:

答案 0 :(得分:2)

了解JWT

JSON Web令牌(JWT)是一种紧凑的URL安全方式​​,用于表示要在双方之间转移的声明。 JWT中的声明被编码为JavaScript对象表示法(JSON)对象,该对象用作JSON Web签名(JWS)结构的有效负载或JSON Web加密(JWE)结构的明文,使声明成为可能数字签名或MAC和/或加密。

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

Json Web令牌标准
https://tools.ietf.org/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();
}

欢迎任何建议!