Tân
Tân

Reputation: 1

Request validation in asp.net mvc

I'm designing 2 websites. The first to upload images and the second to store the images as an image hosting (both of them are using asp.net mvc 5).

The domain name of the first website is: vinachannel.com.

In the first website, I wanna send some images to the hosting via ajax:

var f = new FormData();
$.ajax({
   url: 'https://myimagehosting.com/home/upload',
   type: 'POST',
   data: f,
   processData: false,
   contentType: false
}).done(function (data) {
   // logic...
})

Action Upload in Home controller of the hosting:

[HttpPost]
public JsonResult Upload()
{
   if (Request.Files.Count > 0)
   {
      // start uploading...
   }
}

Now, my problem is: I wanna the image hosting accepts only the requests which are sent from vinachannel.com. Just like:

[HttpPost]
public JsonResult Upload()
{
   if (Request.Files.Count > 0 && Request.Url.AbsoluteUri.StartsWith("vinachannel.com"))
   {
      // start uploading...
   }
}

or using regex:

var reg = new Regex(@"^(https://)?(www\.)?(vinachannel\.com)(.+)$");
if (Request.Files.Count > 0 && reg.IsMatch(Request.Url.AbsoluteUri))
{
   // start uploading...
}

My question: How can I custom an attribute to validate all requests for action Upload?

[VinaChannel] // only requests from site vinachannel.com
[HttpPost]
public JsonResult Upload()
{
   // ...
}

UPDATE: (based on @David's comment and following the article)

public class VinaChannelFilter : ActionFilterAttribute, IActionFilter
{
    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        var reg = new Regex(@"^(https://)?(www\.)?(vinachannel\.com)(.+)$");
        if (reg.IsMatch(HttpContext.Current.Request.Url.AbsoluteUri))
        {
           // what's next here...?
        }
        this.OnActionExecuting(filterContext);
    }
}

Upvotes: 0

Views: 846

Answers (2)

Shyju
Shyju

Reputation: 218722

You may create a custom action filter which inspects the request headers and see where the request is coming from and use that values to determine, whether to allow /deny further processing. the Referer header is the one you might want to use.

public class VerifyDomain : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var expectedHost = "domainnameyouwanttocheck";
        var headers = filterContext.HttpContext.Request.Headers;

        if (!String.IsNullOrEmpty(headers["Referer"]) 
                                      && new Uri(headers["Referer"]).Host == expectedHost)
        {
            base.OnActionExecuting(filterContext);
        }
        else
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }           
    }
}

And decorate your action method/controller with the action filter

[VerifyDomain]
[HttpPost]
public ActionResult Upload()
{
  // to do : return something
}

When this endpoint is being accessed from anywhere other than the value you have in the expectedHost variable, the caller will get 401 Unauthorized response. You may update the if condition to check for a list of expectedHost name's to support your local development environment as well.

Upvotes: 2

Uriil
Uriil

Reputation: 12618

Upload() is on myimagehosting.com, right? Then HttpContext.Current.Request.Url.AbsoluteUri will return Uri on myimagehosting.com domain, to get source address you need to get referrer: HttpContext.Current.Request.UrlReferrer.AbsolutePath. But the problem is, it can be easily forged, so depending on your needs, you probably will have to implement more complex Authentication/Authorization logic

Upvotes: 1

Related Questions