Asp.net mvc webapi practical interface encryption method example, mvcwebapi

Source: Internet
Author: User

Asp.net mvc webapi practical interface encryption method example, mvcwebapi

In many projects, because webapis are open to the outside world, we need to consider the security of interface data exchange.

There are also many security mechanisms, such as the two-way certificate method when andriod and webapi exchange data, but the development cost is relatively high,

Today, we are not going to introduce this knowledge. Let's talk about a simple and common security exchange mechanism.

To remind readers,Currently, all encryption mechanisms are not absolutely secure.!

Our goal is that it is invalid for any user or software to obtain the url of our webapi to access this address again!

To achieve this goal, we must add a timestamp to the url, but this is not enough. You can modify our timestamp!

Therefore, we can encrypt the timestamp with MD5, but this is still not enough. Users can directly encrypt the timestamp with md5, because some need to introduce an absolute security

And add other parameters for obfuscation!

Note: This key must be saved in the app and in our webapi!

So we agreed on the formula: encryption result = md5 (timestamp + Random Number + key + post or get parameters)

The following code is written through the above formula:

Because my environment is asp.net mvc, rewrite an Encryption Class ApiSecurityFilter

1. Get Parameters

if (request.Headers.Contains("timestamp"))    timestamp = HttpUtility.UrlDecode(request.Headers.GetValues("timestamp").FirstOrDefault());   if (request.Headers.Contains("nonce"))    nonce = HttpUtility.UrlDecode(request.Headers.GetValues("nonce").FirstOrDefault());   if (request.Headers.Contains("signature"))    signature = HttpUtility.UrlDecode(request.Headers.GetValues("signature").FirstOrDefault());   if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(signature))    throw new SecurityException();

2. Determine whether the timestamp exceeds the specified time

 double ts = 0;   bool timespanvalidate = double.TryParse(timestamp, out ts);   bool falg = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds - ts > 60 * 1000;   if (falg || (!timespanvalidate))    throw new SecurityException();

3. parameters are extracted using POST, DELETE, and UPDATE methods.

 case "POST":    case "PUT":    case "DELETE":     Stream stream = HttpContext.Current.Request.InputStream;     StreamReader streamReader = new StreamReader(stream);     sortedParams = new SortedDictionary<string, string>(new JsonSerializer().Deserialize<Dictionary<string, string>>(new JsonTextReader(streamReader)));     break;

4. GET Parameters Extraction

case "GET":     IDictionary<string, string> parameters = new Dictionary<string, string>();     foreach (string key in HttpContext.Current.Request.QueryString)     {      if (!string.IsNullOrEmpty(key))      {       parameters.Add(key, HttpContext.Current.Request.QueryString[key]);      }     }     sortedParams = new SortedDictionary<string, string>(parameters);     break;

5. sort and splice the above parameters to form the fourth parameter in the agreed formula for md5.

   StringBuilder query = new StringBuilder();   if (sortedParams != null)   {    foreach (var sort in sortedParams.OrderBy(k => k.Key))    {     if (!string.IsNullOrEmpty(sort.Key))     {      query.Append(sort.Key).Append(sort.Value);     }    }    data = query.ToString().Replace(" ", "");   }

6. Start to agree on the formula calculation result and compare whether the passed results are consistent

 var md5Staff = Seedwork.Utils.CharHelper.MD5(string.Concat(timestamp + nonce + staffId + data), 32);   if (!md5Staff.Equals(signature))    throw new SecurityException();

The complete code is as follows:

public class ApiSecurityFilter : ActionFilterAttribute {  public override void OnActionExecuting(HttpActionContext actionContext)  {   var request = actionContext.Request;   var method = request.Method.Method;   var staffId = "^***********************************$";   string timestamp = string.Empty, nonce = string.Empty, signature = string.Empty;   if (request.Headers.Contains("timestamp"))    timestamp = request.Headers.GetValues("timestamp").FirstOrDefault();   if (request.Headers.Contains("nonce"))    nonce = request.Headers.GetValues("nonce").FirstOrDefault();   if (request.Headers.Contains("signature"))    signature = request.Headers.GetValues("signature").FirstOrDefault();   if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(signature))    throw new SecurityException();   double ts = 0;   bool timespanvalidate = double.TryParse(timestamp, out ts);   bool falg = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds - ts > 60 * 1000;   if (falg || (!timespanvalidate))    throw new SecurityException("timeSpanValidate");   var data = string.Empty;   IDictionary<string, string> sortedParams = null;   switch (method.ToUpper())   {    case "POST":    case "PUT":    case "DELETE":     Stream stream = HttpContext.Current.Request.InputStream;     StreamReader streamReader = new StreamReader(stream);     sortedParams = new SortedDictionary<string, string>(new JsonSerializer().Deserialize<Dictionary<string, string>>(new JsonTextReader(streamReader)));     break;         case "GET":     IDictionary<string, string> parameters = new Dictionary<string, string>();     foreach (string key in HttpContext.Current.Request.QueryString)     {      if (!string.IsNullOrEmpty(key))      {       parameters.Add(key, HttpContext.Current.Request.QueryString[key]);      }     }     sortedParams = new SortedDictionary<string, string>(parameters);     break;    default:     throw new SecurityException("defaultOptions");   }   StringBuilder query = new StringBuilder();   if (sortedParams != null)   {    foreach (var sort in sortedParams.OrderBy(k => k.Key))    {     if (!string.IsNullOrEmpty(sort.Key))     {      query.Append(sort.Key).Append(sort.Value);     }    }    data = query.ToString().Replace(" ", "");   }     var md5Staff = Seedwork.Utils.CharHelper.MD5(string.Concat(timestamp + nonce + staffId + data), 32);   if (!md5Staff.Equals(signature))    throw new SecurityException("md5Staff");   base.OnActionExecuting(actionContext);  }  public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)  {   base.OnActionExecuted(actionExecutedContext);  } }

7. Add the configuration class in asp.net mvc.

 public static class WebApiConfig {  public static void Register(HttpConfiguration config)  {   // Web API configuration and services   config.Filters.Add(new ApiSecurityFilter());   config.Filters.Add(new ApiHandleErrorAttribute());   // Web API routes   config.MapHttpAttributeRoutes();   config.Routes.MapHttpRoute(    name: "DefaultApi",    routeTemplate: "api/{controller}/{id}",    defaults: new { id = RouteParameter.Optional }   );  } }

8. Add a log writing class

 public class ApiHandleErrorAttribute: ExceptionFilterAttribute {  /// <summary>  /// add by laiyunba   /// </summary>  /// <param name="filterContext">context oop</param>  public override void OnException(HttpActionExecutedContext filterContext)  {   LoggerFactory.CreateLog().LogError(Messages.error_unmanagederror, filterContext.Exception);  } }

9. Use the mini-program test interface

 var data = {  UserName: username,  Password: password,  Action: 'Mobile',  Sms: ''  };  var timestamp = util.gettimestamp();  var nonce = util.getnonce();  if (username && password) {  wx.request({   url: rootUrl + '/api/login',   method: "POST",   data: data,   header: {   'content-type': 'application/json',   'timestamp': timestamp,   'nonce': nonce,   'signature': util.getMD5Staff(data, timestamp, nonce)   },   success: function (res) {   if (res.data) {

1) The getMD5Staff function:

Function getMD5Staff (queryData, timestamp, nonce) {var staffId = getstaffId (); // synchronize the saved key with webapi var data = dictionaryOrderWithData (queryData ); return md5.md5 (timestamp + nonce + staffId + data );}

2) dictionaryOrderWithData function:

function dictionaryOrderWithData(dic) { //eg {x:2,y:3,z:1} var result = ""; var sdic = Object.keys(dic).sort(function (a, b) { return a.localeCompare(b) }); var value = ""; for (var ki in sdic) { if (dic[sdic[ki]] == null) {  value = "" } else {  value = dic[sdic[ki]]; } result += sdic[ki] + value; } return result.replace(/\s/g, "");}

10. Test log

LaiyunbaApp Error: 2: 09:15:25 Unmanaged error in aplication, the exception information is Exception: System. Security. SecurityException: Security Error. In DistributedServices. mainBoundedContext. filterAttribute. apiSecurityFilter. onActionExecuting (HttpActionContext actionContext) in System. web. http. filters. actionFilterAttribute. onActionExecutingAsync (HttpActionContext actionContext, CancellationToken cancellationToken) --- The End Of The stack trace in the previous position where an exception is thrown --- in System. runtime. compilerServices. taskAwaiter. throwForNonSuccess (Task task) in System. runtime. compilerServices. taskAwaiter. handleNonSuccessAndDebuggerNotification (Task task) in System. web. http. filters. actionFilterAttribute. <ExecuteActionFilterAsyncCore> d _ 0. moveNext () --- The End Of The stack trace in the previous position where the exception is thrown --- in System. runtime. compilerServices. taskAwaiter. throwForNonSuccess (Task task) in System. runtime. compilerServices. taskAwaiter. handleNonSuccessAndDebuggerNotification (Task task) in System. web. http. controllers. actionFilterResult. <ExecuteAsync> d _ 2. moveNext () --- The End Of The stack trace in the previous position where the exception is thrown --- in System. runtime. compilerServices. taskAwaiter. throwForNonSuccess (Task task) in System. runtime. compilerServices. taskAwaiter. handleNonSuccessAndDebuggerNotification (Task task) in System. web. http. controllers. predictionfilterresult. <ExecuteAsync> d _ 0. the region of the assembly where MoveNext () fails is: MyComputerLogicalOperationStack = 09:15:25 09:15:25 DateTime = 2017-10-18T01: 15: 25.20.17z2017-10-18 09:15:25 Callstack = in System. environment. getStackTrace (Exception e, Boolean needFileInfo) in System. environment. get_StackTrace () in System. diagnostics. traceEventCache. get_Callstack () in System. diagnostics. traceListener. writeFooter (TraceEventCache eventCache) in System. diagnostics. traceSource. traceEvent (TraceEventType eventType, Int32 id, String message) in the Infrastructure. crosscutting. netFramework. logging. traceSourceLog. traceInternal (TraceEventType eventType, String message) in Infrastructure. crosscutting. netFramework. logging. traceSourceLog. logError (String message, Exception exception, Object [] args) in System. web. http. filters. predictionfilterattribute. onExceptionAsync (HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) in System. web. http. filters. predictionfilterattribute. <ExecuteExceptionFilterAsyncCore> d _ 0. moveNext () in System. runtime. compilerServices. asyncTaskMethodBuilder. start [TStateMachine] (TStateMachine & stateMachine) in System. web. http. filters. predictionfilterattribute. executeExceptionFilterAsyncCore (HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) in System. web. http. filters. predictionfilterattribute. system. web. http. filters. IExceptionFilter. executeExceptionFilterAsync (HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) in System. web. http. controllers. predictionfilterresult. <ExecuteAsync> d _ 0. moveNext () in System. runtime. compilerServices. asyncTaskMethodBuilder '1. start [TStateMachine] (TStateMachine & stateMachine) in System. web. http. controllers. predictionfilterresult. executeAsync (CancellationToken cancellationToken) in System. web. http. apiController. executeAsync (HttpControllerContext controllerContext, CancellationToken cancellationToken) in System. web. http. dispatcher. httpControllerDispatcher. <SendAsync> d _ 1. moveNext () in System. runtime. compilerServices. asyncTaskMethodBuilder '1. start [TStateMachine] (TStateMachine & stateMachine) in System. web. http. dispatcher. httpControllerDispatcher. sendAsync (HttpRequestMessage request, CancellationToken cancellationToken) in System. net. http. httpMessageInvoker. sendAsync (HttpRequestMessage request, CancellationToken cancellationToken) in System. web. http. dispatcher. httpRoutingDispatcher. sendAsync (HttpRequestMessage request, CancellationToken cancellationToken)

At this point, all the webapi encryption has been completed. The preceding exception is a direct access url error. Normal access is allowed only in the app environment.

Summary: There are a lot of webapi encryption secrets, such as small programs. It is difficult for users to obtain the source code of the client app. To know our key, let alone. Of course, we also need to regularly update the app version.

Apps such as app for andriod or ios can use two-way certificates, or use our above method, and then reinforce the app to prevent malicious users from cracking the key. Of course, no matter what, the first thing we need to do is the https protocol!

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.