How to secure access to MVC actions that return JSON
I have a public facing website that is developed with ASP.NET MVC 3. The MVC application contains controllers with actions that return JSON. The web pages execute AJAX requests against the act开发者_开发百科ions that return JSON.
Even though the data that is published with the JSON action is not sensitive, it is proprietary, and I’m concerned that anybody can call the actions that return JSON through cross domain calls or custom applications. Is there a way to only allow my MVC application webpages access to the actions that return JSON? Does ODATA provide any benefits for solving this problem?
Does anyone know of resources that describes this issue as a liability and how to solve it?
If your application is public, then its more tricky. There's the ValidateAntiForgeryToken
attribute which can help against XSS and random requests.
If you have a password protected site, use the Authorize
attribute.
OData has the same set of problems the MVC site would have.
If you are using Roles, You can restrict access using Authorize attribute.
I have a similar setup, but in mine iOS devices have to communicate with the pages that respond in JSON. I ended up creating an ActionFilterAttribute
that verifies that the device is 1) added to the list of allowed devices by its UDId and 2) that the user assigned to the device is active (currently employed). The problem is that this forces me into POST requests, which to me it really isn't a problem, but to you it may be since you may be allowing GET requests. I also could be wrong, I think the model binder will still parse the objects from a GET request and the filter will probably still work.
Anyway, here's the code to my filter as it is, modifier as you see fit:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
internal sealed class VerifyDeviceAttribute : ActionFilterAttribute {
[Inject]
public DeviceProvider DeviceProvider { private get; set; }
public override void OnActionExecuting(
ActionExecutingContext ActionExecutingContext) {
string UDId = ActionExecutingContext.HttpContext.Request.Form["Authorization.UDId"];
if (this.DeviceProvider.Exists(UDId) && !this.DeviceProvider.Get(UDId).User.Active) {
ActionExecutingContext.Controller.ViewData.ModelState.AddModelError("User", "The user is not active");
} else if (!this.DeviceProvider.Exists(UDId)) {
ActionExecutingContext.Controller.ViewData.ModelState.AddModelError("UDId", "The UDId is empty");
};
}
}
You may notice that I'm pushing errors into the controller ModelState
, if there's any, and in the action results I always check the model state before formatting the response, so make sure you're always checking your ModelState
!
If you really want to get secure, you could treat the controllers that return JSON the same way you'd treat your database and deploy them to a separate app that sits behind the firewall, whilst the front end edge server sits in the DMZ.
The clients can connect to the front end web server which in turn calls the JSON resources behind the firewall. The client can't directly connect to the JSON resources.
You can use the ValidateAntiForgeryToken to prevent people from making requests to your methods however since you are working with the data client-side there are a plethora of other ways for them to access your data once it is sent to the client. There is very little (if anything) you can do to prevent data or information you allow to be publicly accessible form being mined in some fashion
精彩评论