Анти-поддельная система на ASP.Net MVC

Когда я помещаю следующий код:

 @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" }))
    {
        @Html.AntiForgeryToken()
        <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
    }

@Html.AntiForgeryToken()

part is throwig следующее исключение:

Предоставленный идентификатор типа "System.Web.Security.FormsIdentity" отмечен как IsAuthenticated = true, но не имеет значения для Name. По умолчанию система анти-подделки требует, чтобы все аутентифицированные идентификаторы имели уникальное имя. Если невозможно предоставить уникальное имя для этого удостоверения, рассмотрите возможность установки статического свойства AntiForgeryConfig.AdditionalDataProvider экземпляру типа, который может предоставить определенный тип уникального идентификатора для текущего пользователя.

Я проверил множество примеров и попытался выполнить поиск в Интернете, но я не могу найти никаких объяснений. Я хотел бы знать, почему эта ошибка происходит со мной? И как решить это, чтобы использовать антифрикцию.

Ответ 1

Это говорит вам, что это не сработает, потому что, несмотря на вход в систему, Membership.GetUser().UserName не предоставляет имя, которое можно использовать для хеширования.

Итак, ваша настоящая проблема: "Почему мой зарегистрированный пользователь не имеет имени пользователя?"

Ответ 2

Могут быть некоторые случаи, когда во входном имени пользователя не установлено Identity.Name(в моем случае мне нужно интегрировать мое приложение с какой-то сумасшедшей системой входа в систему). Тогда есть два пути:

1) unsecure - все пользователи будут обрабатываться одинаково с помощью антикоррозионной системы, независимо от их статуса auth

// System.Web.WebPages.dll
using System.Web.Helpers;

// not a production solution
public class MvcApplication : HttpApplication {
  protected void Application_Start() {
    AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
  }
}

2) secure - предоставить свой собственный (пользовательский) способ, как вы отличаете своих пользователей.

using System;
using System.Globalization;
using System.Web;
using System.Web.Helpers;

public class ContoscoAntiForgeryAdditionalDataProvider : IAntiForgeryAdditionalDataProvider {
  public string GetAdditionalData(HttpContextBase context) {
    if (context == null) {
      throw new ArgumentNullException("context");
    }

    var contoscoContext = new ContoscoHttpContext(context);
    int userID = contoscoContext.GetUserID().GetValueOrDefault();
    return Convert.ToString(userID, CultureInfo.InvariantCulture);
  }

  public bool ValidateAdditionalData(HttpContextBase context, string additionalData) {
    string data = GetAdditionalData(context);
    return string.Compare(data, additionalData, StringComparison.Ordinal) == 0;
  }
}


public class MvcApplication : HttpApplication {
  protected void Application_Start() {
    AntiForgeryConfig.AdditionalDataProvider = 
      new ContoscoAntiForgeryAdditionalDataProvider(); 
  }
}

где ContoscoHttpContext - класс, который возвращает UserID (или любой уникальный токен пользователя) на основе текущего контекста (т.е. HttpContextBase):

public class ContoscoHttpContext {
  private HttpContextBase _context;
  public ContoscoHttpContext(HttpContextBase context) {
    _context = context;
  }
  public int? GetUserID() {
    // TODO: provide your own implementation how to get user id
    // based on HttpContextBase stored in _context
    // in my case it was something like 
    // return ((ContoscoPrincipal)_context.User).UserID;
  }
}