Ответ 1
Причиной по умолчанию для DenyGet является MSDN со ссылкой на Блог Фила Хаака для получения дополнительной информации. Похож на уязвимость межсайтового скриптинга.
Как часть обновления ASP.NET MVC 2 Beta 2, по умолчанию запросы JSON GET запрещены. Похоже, вам нужно установить поле JsonRequestBehavior
в JsonRequestBehavior.AllowGet
, прежде чем возвращать объект JsonResult
с вашего контроллера.
public JsonResult IsEmailValid(...)
{
JsonResult result = new JsonResult();
result.Data = ..... ;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
В чем причина этого? Если я использую JSON GET, чтобы попытаться выполнить удаленную проверку, следует ли использовать другую технику?
Причиной по умолчанию для DenyGet является MSDN со ссылкой на Блог Фила Хаака для получения дополнительной информации. Похож на уязвимость межсайтового скриптинга.
HTTP GET по умолчанию отключен как часть защиты ASP.NET Cross-Site Request Forgery (CSRF/XSRF). Если ваши веб-службы принимают запросы GET, они могут быть уязвимы для сторонних сайтов, обрабатывающих запросы через теги <script />
и потенциально собирать ответ, изменяя настройки JavaScript.
Однако стоит отметить, что отключения GET-запросов недостаточно для предотвращения атак CSRF, и это единственный способ защитить вашу службу от типа атаки, описанного выше. См. Надежная защита для кросс-сайта запроса форекс для хорошего анализа различных векторов атак и способов защиты от них.
У меня также возникла проблема, когда я перенес свой веб-сайт MVC из Visual Studio 2008 в Visual Studio 2010.
Ниже приведена основная aspx, у нее есть ViewData, которая вызывает контроллер категорий, чтобы заполнить ViewData [ "Категории" ] с помощью коллекции SelectList. Также существует script, чтобы вызвать контроллер подкатегории, чтобы заполнить вторую комбинацию с помощью javascript. Теперь я смог исправить это, добавив атрибут AlloGet на этот второй контроллер.
Здесь aspx и javascript
<head>
<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryId").change(function () {
var categoryId = $(this)[0].value;
$("#ctl00_MainContent_SubcategoryId").empty();
$("#ctl00_MainContent_SubcategoryId").append("<option value=''>-- select a category --</option>");
var url = "/Subcategory/Subcategories/" + categoryId;
$.getJSON(url, { "selectedItem": "" }, function (data) {
$.each(data, function (index, optionData) {
$("#ctl00_MainContent_SubcategoryId").append("<option value='" + optionData.SubcategoryId + "'>" + optionData.SubcategoryName + "</option>");
});
//feed our hidden html field
var selected = $("#chosenSubcategory") ? $("#chosenSubcategory").val() : '';
$("#ctl00_MainContent_SubcategoryId").val(selected);
});
}).change();
});
</script>
<body>
<% using (Html.BeginForm()) {%>
<label for="CategoryId">Category:</label></td>
<%= Html.DropDownList("CategoryId", (SelectList)ViewData["Categories"], "--categories--") %>
<%= Html.ValidationMessage("category","*") %>
<br/>
<label class="formlabel" for="SubcategoryId">Subcategory:</label><div id="subcategoryDiv"></div>
<%=Html.Hidden("chosenSubcategory", TempData["subcategory"])%>
<select id="SubcategoryId" runat="server">
</select><%= Html.ValidationMessage("subcategory", "*")%>
<input type="submit" value="Save" />
<%}%>
здесь мой контроллер для подкатегорий
public class SubcategoryController : Controller
{
private MyEntities db = new MyEntities();
public int SubcategoryId { get; set; }
public int SubcategoryName { get; set; }
public JsonResult Subcategories(int? categoryId)
{
try
{
if (!categoryId.HasValue)
categoryId = Convert.ToInt32(RouteData.Values["id"]);
var subcategories = (from c in db.Subcategories.Include("Categories")
where c.Categories.CategoryId == categoryId && c.Active && !c.Deleted
&& c.Categories.Active && !c.Categories.Deleted
orderby c.SubcategoryName
select new { SubcategoryId = c.SubcategoryId, SubcategoryName = c.SubcategoryName }
);
//just added the allow get attribute
return this.Json(subcategories, JsonRequestBehavior.AllowGet);
}
catch { return this.Json(null); }
}
Я не знаю, является ли это причиной того, что они решили изменить это значение по умолчанию, но вот мой опыт:
Когда некоторые браузеры видят GET, они думают, что могут кэшировать результат. Поскольку AJAX обычно используется для небольших запросов, чтобы получать самую последнюю информацию с сервера, кеширование этих результатов обычно приводит к неожиданному поведению. Если вы знаете, что данный вход будет возвращать один и тот же результат каждый раз (например, "пароль" не может использоваться в качестве пароля, независимо от того, когда вы спрашиваете меня), тогда GET будет прекрасным, и кеширование браузера может фактически повысить производительность в случае кто-то пытается несколько раз проверять один и тот же ввод. Если, с другой стороны, вы ожидаете другого ответа в зависимости от текущего состояния данных на стороне сервера ( "myfavoriteusername", возможно, было доступно 2 минуты назад, но оно было принято с тех пор), вы должны использовать POST, чтобы избежать браузер считает, что первый ответ по-прежнему является правильным.