方式一:AuthorizeFilter
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyTest.Common { public class SignAuthorzation : AuthorizeFilter { string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥 int timeOut = 120; //签名超时时间(单位:秒) public override async Task OnAuthorizationAsync(AuthorizationFilterContext context) { try { var httpContext = context.HttpContext; if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico") { var sign = string.Empty; //签名 var timestamp = string.Empty;//时间戳 var query = new Dictionary<string, object>(); if (httpContext.Request.Method == "GET") {//get方式获取请求参数 var queryParam = httpContext.Request.Query.Keys.ToArray(); foreach (var item in queryParam) { var val = httpContext.Request.Query[item].ToString(); if (item == "sign") { sign = val; continue; } if (item == "timestamp") { timestamp = httpContext.Request.Query[item].ToString(); } query.Add(item, val); } } else {//post方式获取请求参数 using (Stream stream = httpContext.Request.Body) { byte[] buffer = new byte[httpContext.Request.ContentLength.Value]; stream.Read(buffer, 0, buffer.Length); httpContext.Request.Body = new System.IO.MemoryStream(buffer); string postData = Encoding.UTF8.GetString(buffer); query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData); var postParam = string.Empty; foreach (var item in query.ToList()) { if (item.Key == "sign") { sign = item.Value.ToString(); query.Remove(item.Key); } if (item.Key == "timestamp") { timestamp = item.Value.ToString(); } } } } if (string.IsNullOrWhiteSpace(sign)) { context.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数sign" }); return; } if (string.IsNullOrWhiteSpace(timestamp)) { context.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数timestamp" }); return; } var requestTime = ConvertStringToDateTime(timestamp); long time1 = DateTime.Now.Ticks; long time2 = requestTime.Ticks; long interval = (time1 - time2) / 10000000; //判断签名时间 if (interval > timeOut) { context.Result = new JsonResult(new { Code = 0, Msg = "签名超时" }); } else { //生成签名 var signStr = GetQueryString(query); //MD5加密 var signReal = signStr.Md5().ToLower(); //判断签名 if (signReal != sign.ToLower()) { context.Result = new JsonResult(new { Code = 0, Msg = "签名错误" }); } } } } catch (Exception ex) { context.Result = new JsonResult(new { Code = 500, Msg = "签名验证异常" }); } } /// <summary> /// 拼接参数 /// 签名生成规则如下:参与签名的字段包括请求的参数, timestamp(时间戳),签名密钥 signaturekey。 /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1 /// </summary> /// <param name="parames"></param> /// <returns></returns> public string GetQueryString(Dictionary<string, object> parames) { var arr = parames.Keys.ToArray(); Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序 List<string> query = new List<string>(); if (parames == null || parames.Count == 0) { return ""; } foreach (var item in arr) { query.Add($"{item}={parames[item]}"); } query.Add($"signaturekey={signaturekey}"); return string.Join("&", query); } /// <summary> /// 时间戳转换时间 /// </summary> /// <param name=”timestamp”></param> /// <returns></returns> public DateTime ConvertStringToDateTime(string timestamp) { DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long lTime = long.Parse(timestamp + "0000"); TimeSpan toNow = new TimeSpan(lTime); return dtStart.Add(toNow); } } }
在Startup.cs的ConfigureServices方法中添加以下语句:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.Filters.Add<SignAuthorzation>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
方式二:ActionFilterAttribute
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace MyTest.Common { public class SignAuthFilterAttribute : ActionFilterAttribute { string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥 int timeOut = 120; //签名超时时间(单位:秒) public override void OnActionExecuting(ActionExecutingContext actionContext) { try { var httpContext = actionContext.HttpContext; if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico") { var sign = string.Empty; //签名 var timestamp = string.Empty;//时间戳 var query = new Dictionary<string, object>(); if (httpContext.Request.Method == "GET") {//get方式获取请求参数 var queryParam = httpContext.Request.Query.Keys.ToArray(); foreach (var item in queryParam) { var val = httpContext.Request.Query[item].ToString(); if (item == "sign") { sign = val; continue; } if (item == "timestamp") { timestamp = httpContext.Request.Query[item].ToString(); } query.Add(item, val); } } else {//post方式获取请求参数 using (Stream stream = httpContext.Request.Body) { httpContext.Request.Body.Position = 0; byte[] buffer = new byte[httpContext.Request.ContentLength.Value]; stream.Read(buffer, 0, buffer.Length); string postData = Encoding.UTF8.GetString(buffer); query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData); foreach (var item in query.ToList()) { if (item.Key == "sign") { sign = item.Value.ToString(); query.Remove(item.Key); } if (item.Key == "timestamp") { timestamp = item.Value.ToString(); } } } } if (string.IsNullOrWhiteSpace(sign)) { actionContext.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数sign" }); return; } if (string.IsNullOrWhiteSpace(timestamp)) { actionContext.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数timestamp" }); return; } var requestTime = ConvertStringToDateTime(timestamp); long time1 = DateTime.Now.Ticks; long time2 = requestTime.Ticks; long interval = (time1 - time2) / 10000000; //判断签名时间 if (interval > timeOut) { actionContext.Result = new JsonResult(new { Code = 0, Msg = "签名超时" }); } else { //生成签名 var signStr = GetQueryString(query); //MD5加密 var signReal = signStr.Md5().ToLower(); //判断签名 if (signReal != sign.ToLower()) { actionContext.Result = new JsonResult(new { Code = 0, Msg = "签名错误" }); } } } } catch (Exception ex) { actionContext.Result = new JsonResult(new { Code = 500, Msg = "签名验证异常" }); } } /// <summary> /// 拼接参数 /// 签名生成规则如下:参与签名的字段包括请求的参数, timestamp(时间戳),签名密钥 signaturekey。 /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1 /// </summary> /// <param name="parames"></param> /// <returns></returns> public string GetQueryString(Dictionary<string, object> parames) { var arr = parames.Keys.ToArray(); Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序 List<string> query = new List<string>(); if (parames == null || parames.Count == 0) { return ""; } foreach (var item in arr) { query.Add($"{item}={parames[item]}"); } query.Add($"signaturekey={signaturekey}"); return string.Join("&", query); } /// <summary> /// 时间戳转换时间 /// </summary> /// <param name=”timestamp”></param> /// <returns></returns> public DateTime ConvertStringToDateTime(string timestamp) { DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long lTime = long.Parse(timestamp + "0000"); TimeSpan toNow = new TimeSpan(lTime); return dtStart.Add(toNow); } } }
在Startup.cs的ConfigureServices方法中添加以下语句:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.Filters.Add<SignAuthFilterAttribute>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
方式三:
using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace MyTest.Common { public class SignCheck { string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥 int timeOut = 120; //签名超时时间(单位:秒) private readonly RequestDelegate _next; public SignCheck(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext httpContext) { try { if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico") { var sign = string.Empty; //签名 var timestamp = string.Empty;//时间戳 var query = new Dictionary<string, object>(); if (httpContext.Request.Method == "GET") {//get方式获取请求参数 var queryParam = httpContext.Request.Query.Keys.ToArray(); foreach (var item in queryParam) { var val = httpContext.Request.Query[item].ToString(); if (item == "sign") { sign = val; continue; } if (item == "timestamp") { timestamp = httpContext.Request.Query[item].ToString(); } query.Add(item, val); } } else { var memery = new System.IO.MemoryStream(); httpContext.Request.Body.CopyTo(memery); memery.Position = 0; var postData = new System.IO.StreamReader(memery, System.Text.UTF8Encoding.UTF8).ReadToEnd(); memery.Position = 0; httpContext.Request.Body = memery; query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData); var postParam = string.Empty; foreach (var item in query.ToList()) { if (item.Key == "sign") { sign = item.Value.ToString(); query.Remove(item.Key); } if (item.Key == "timestamp") { timestamp = item.Value.ToString(); } } } if (string.IsNullOrWhiteSpace(sign)) { httpContext.Response.StatusCode = 401; return httpContext.Response.WriteAsync("缺少签名参数sign"); } if (string.IsNullOrWhiteSpace(timestamp)) { httpContext.Response.StatusCode = 401; return httpContext.Response.WriteAsync("缺少签名参数timestamp"); } var requestTime = ConvertStringToDateTime(timestamp); long time1 = DateTime.Now.Ticks; long time2 = requestTime.Ticks; long interval = (time1 - time2) / 10000000; if (interval > timeOut) { httpContext.Response.StatusCode = 401; return httpContext.Response.WriteAsync("Signature error"); } else { //生成签名 var signStr = GetQueryString(query); //MD5加密 var signReal = signStr.Md5().ToLower(); //判断签名 if (signReal != sign.ToLower()) { httpContext.Response.StatusCode = 401; return httpContext.Response.WriteAsync("Signature error"); } } } return _next(httpContext); } catch (Exception ex) { return null; } } /// <summary> /// 拼接参数 /// 签名生成规则如下:参与签名的字段包括请求的参数, timestamp(时间戳),签名密钥 signaturekey。 /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1 /// </summary> /// <param name="parames"></param> /// <returns></returns> public string GetQueryString(Dictionary<string, object> parames) { var arr = parames.Keys.ToArray(); Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序 List<string> query = new List<string>(); if (parames == null || parames.Count == 0) { return ""; } foreach (var item in arr) { query.Add($"{item}={parames[item]}"); } query.Add($"signaturekey={signaturekey}"); return string.Join("&", query); } /// <summary> /// 时间戳转换时间 /// </summary> /// <param name=”timestamp”></param> /// <returns></returns> public DateTime ConvertStringToDateTime(string timestamp) { DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long lTime = long.Parse(timestamp + "0000"); TimeSpan toNow = new TimeSpan(lTime); return dtStart.Add(toNow); } } }
在Startup.cs的Configure方法中添加以下语句:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseMiddleware<SignCheck>(); app.UseHttpsRedirection(); app.UseMvc(); }
Md5加密方式:
using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace MyTest.Common { public static class EncryptHelper { /// <summary> /// 基于Md5的自定义加密字符串方法:输入一个字符串,返回一个由32个字符组成的十六进制的哈希散列(字符串)。 /// </summary> /// <param name="str">要加密的字符串</param> /// <returns>加密后的十六进制的哈希散列(字符串)</returns> public static string Md5(this string str) { var buffer = Encoding.Default.GetBytes(str); var data = MD5.Create().ComputeHash(buffer); var sb = new StringBuilder(); foreach (var t in data) { sb.Append(t.ToString("X2")); } return sb.ToString(); } } }
前端调用示例:
<script type="text/javascript" src="jquery-2.1.4.js"></script> <script type="text/javascript" src="md5.js"></script> <input type="button" value="测试" onclick="GetUser()" /> <script type="text/javascript"> function getNewObj(obj) { var timestamp = (new Date()).valueOf();//时间戳 obj.timestamp = timestamp; var newKey = Object.keys(obj).sort(); var queryArray = new Array(); for (var i = 0; i < newKey.length; i++) { queryArray.push(newKey[i] + "=" + obj[newKey[i]]); } queryArray.push("signaturekey=fba503abf3a411e9b97f00163e129d15"); var signStr = queryArray.join("&"); var sign = md5(signStr); obj.sign = sign; return obj; } function GetUser() { var item = { "PageIndex": 1, "PageSize": 10, "UserId": 1, "Status": -1 } var newobj1 = getNewObj(item); $.ajax({ url: "http://localhost:9002/User/GetUser", dataType: "json", async: true, data: newobj1, type: "GET", success: function (result) { console.log(result) alert(JSON.stringify(result)); }, error: function () { } }); } </script>
如果是前端直接调用需要设置api允许跨域:
在Startup.cs的ConfigureServices方法中增加:
services.AddCors(option => option.AddPolicy("AllowCors", builder => builder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().AllowAnyOrigin()));
在Startup.cs的Configure方法中增加:
app.UseCors("AllowCors");
md5.js
/* * JavaScript MD5 1.0.1 * https://github.com/blueimp/JavaScript-MD5 * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT * * Based on * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ /*jslint bitwise: true */ /*global unescape, define */ (function ($) { 'use strict'; /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF), msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } /* * These functions implement the four basic operations the algorithm uses. */ function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); } function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); } function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function binl_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << (len % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var i, olda, oldb, oldc, oldd, a = 1732584193, b = -271733879, c = -1732584194, d = 271733878; for (i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; a = md5_ff(a, b, c, d, x[i], 7, -680876936); d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); b = md5_gg(b, c, d, a, x[i], 20, -373897302); a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); d = md5_hh(d, a, b, c, x[i], 11, -358537222); c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); a = md5_ii(a, b, c, d, x[i], 6, -198630844); d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } return [a, b, c, d]; } /* * Convert an array of little-endian words to a string */ function binl2rstr(input) { var i, output = ''; for (i = 0; i < input.length * 32; i += 8) { output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); } return output; } /* * Convert a raw string to an array of little-endian words * Characters >255 have their high-byte silently ignored. */ function rstr2binl(input) { var i, output = []; output[(input.length >> 2) - 1] = undefined; for (i = 0; i < output.length; i += 1) { output[i] = 0; } for (i = 0; i < input.length * 8; i += 8) { output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); } return output; } /* * Calculate the MD5 of a raw string */ function rstr_md5(s) { return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); } /* * Calculate the HMAC-MD5, of a key and some data (raw strings) */ function rstr_hmac_md5(key, data) { var i, bkey = rstr2binl(key), ipad = [], opad = [], hash; ipad[15] = opad[15] = undefined; if (bkey.length > 16) { bkey = binl_md5(bkey, key.length * 8); } for (i = 0; i < 16; i += 1) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); } /* * Convert a raw string to a hex string */ function rstr2hex(input) { var hex_tab = '0123456789abcdef', output = '', x, i; for (i = 0; i < input.length; i += 1) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); } return output; } /* * Encode a string as utf-8 */ function str2rstr_utf8(input) { return unescape(encodeURIComponent(input)); } /* * Take string arguments and return either raw or hex encoded strings */ function raw_md5(s) { return rstr_md5(str2rstr_utf8(s)); } function hex_md5(s) { return rstr2hex(raw_md5(s)); } function raw_hmac_md5(k, d) { return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)); } function hex_hmac_md5(k, d) { return rstr2hex(raw_hmac_md5(k, d)); } function md5(string, key, raw) { if (!key) { if (!raw) { return hex_md5(string); } return raw_md5(string); } if (!raw) { return hex_hmac_md5(key, string); } return raw_hmac_md5(key, string); } if (typeof define === 'function' && define.amd) { define(function () { return md5; }); } else { $.md5 = md5; } }(this));