ASP.NET MVC - проверка подлинности HTTP
Возможно ли, чтобы мое приложение запрашивало имя пользователя и пароль, запрашивая его перед визуализацией представления?
Как и в twitter API для получения информации о вашей учетной записи:
http://twitter.com/account/verify_credentials.xml
Итак, перед отображением вида || файл, он просит вас вставить вам имя пользователя и пароль, я думаю, что это делается непосредственно на сервере, так как запрос на завиток основан на имени пользователя: password так же, как это:
curl -u user:password http://twitter.com/account/verify_credentials.xml
Как я пытаюсь построить API, следуя той же структуре, я хотел бы знать, как я могу это сделать на ASP.NET MVC С#. Я уже использовал это на рубиновых рельсах, и это довольно просто:
before_filter :authenticate
def authenticate
authenticate_or_request_with_http_basic do |username, password|
username == "foo" && password == "bar"
end
Я не думаю, что фильтр [Авторизовать] тот же, поскольку я считаю его просто перенаправлением,
и он перенаправляет вас к внутреннему контроллеру учетных записей, который основан на базе данных учетных записей, в этом случае я буду использовать другую базу данных, в частности, из веб-службы и выполнить проверку после отправки информации.
Но мне нужно действие, чтобы потребовать пользователя и передать учетные данные по его запросу.
Заранее спасибо
UPDATE:
Собственно запрашивать страницу, требующую этой аутентификации (т.е. Twitter)
Я должен был бы объявить это по его запросу
request.Credentials = new NetworkCredential("username", "password");
И это будет отражать подсказку имени пользователя и пароля.
Итак, это точно то же самое, но с другой стороны, если возможно предоставить информацию в приглашении проверки подлинности по запросу, как я мог бы потребовать эту аутентификацию на вместо запроса?
Поэтому каждый раз кто-то пытается сделать запрос к моему приложению, например:
http://myapplication/clients/verify_credentials
он должен запросить имя пользователя и пароль с приглашением этого сервера
поэтому для получения информации о завитке, например, это будет выглядеть как
curl -u user:password http://myapplication/clients/verify_credentials
Ответы
Ответ 1
Ну, для обеспечения базовой аутентификации вам необходимо вернуть код состояния 401. Но выполнение этого приведет к тому, что текущий модуль аутентификации выполнит свой неавторизованный обработчик по умолчанию (для проверки подлинности форм это означает перенаправление на страницу входа).
Я написал ActionFilterAttribte
, чтобы узнать, могу ли я получить нужное поведение, если в web.config
не установлен модуль проверки подлинности.
public class RequireBasicAuthentication : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
var req = filterContext.HttpContext.Request;
if (String.IsNullOrEmpty(req.Headers["Authorization"])) {
var res = filterContext.HttpContext.Response;
res.StatusCode = 401;
res.AddHeader("WWW-Authenticate", "Basic realm=\"Twitter\"");
res.End();
}
}
}
И действие контроллера:
[RequireBasicAuthentication]
public ActionResult Index() {
var cred = System.Text.ASCIIEncoding.ASCII
.GetString(Convert.FromBase64String(
Request.Headers["Authorization"].Substring(6)))
.Split(':');
var user = new { Name = cred[0], Pass = cred[1] };
return Content(String.Format("user:{0}, password:{1}",
user.Name, user.Pass));
}
Это действие успешно печатает имя пользователя и пароль, которые я вводил. Но я действительно сомневаюсь, что это лучший способ сделать это. У вас нет выбора, кроме как запросить имя пользователя и пароль таким образом?
Ответ 2
Вы действительно хотите создать службу, а не веб-приложение, основанное на том, что я прочитал. Я угадываю здесь, но я думаю, что вы выбрали ASP.NET MVC, чтобы воспользоваться маршрутизацией и создать URL-адрес так, как хотите? Исправьте меня, если я ошибаюсь.
На мой взгляд, лучший способ решить проблему, которую вы имеете, - создать веб-службы RESTful с WCF, если вы возвращаете данные. Эта статья должна помочь вам начать работу, если вы хотите пройти этот маршрут.
В противном случае вам нужно будет идти дальше в стек для обработки запроса и проверки подлинности. Если это так, я могу помочь с предоставлением дополнительной информации и кода.
Ответ 3
Я изменил ответ çağdaş, чтобы поместить всю логику в свой собственный атрибут ActionFilter.
public class BasicAuthenticationAttribute : ActionFilterAttribute
{
public string BasicRealm { get; set; }
protected string Username { get; set; }
protected string Password { get; set; }
public BasicAuthenticationAttribute(string username, string password)
{
this.Username = username;
this.Password = password;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var req = filterContext.HttpContext.Request;
var auth = req.Headers["Authorization"];
if (!String.IsNullOrEmpty(auth))
{
var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
var user = new { Name = cred[0], Pass = cred[1] };
if (user.Name == Username && user.Pass == Password) return;
}
var res = filterContext.HttpContext.Response;
res.StatusCode = 401;
res.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
res.End();
}
}
Его можно использовать для установки под базовой аутентификацией всего контроллера:
[BasicAuthenticationAttribute("your-username", "your-password",
BasicRealm = "your-realm")]
public class HomeController : BaseController
{
...
}
или конкретный ActionResult:
public class HomeController : BaseController
{
[BasicAuthenticationAttribute("your-username", "your-password",
BasicRealm = "your-realm")]
public ActionResult Index()
{
...
}
}
ПРИМЕЧАНИЕ. Вышеупомянутая реализация требует, чтобы разработчик вручную ввел имя пользователя и пароль в качестве необходимых параметров ActionFilter, но может быть легко расширен, чтобы обеспечить поддержку любого механизма авторизации (MembershipProvider, Identity ASP.NET, пользовательский пользовательская база на внешней СУБД или файл и т.д.), удалив пользовательский конструктор и соответствующим образом изменив IF IF-блок OnActionExecuting.
Вы также можете читать здесь для получения дополнительной информации.
Ответ 4
Вот путь, который сработал у меня. Это небольшая работа, но это сделает IIS и MVC3 более похожими на все другие системы аутентификации Basic Http, такие как Apache...
Шаг 1.
Убедитесь, что для IIS установлена "Основная проверка подлинности".
(Пример: Панель управления → Программы и функции → Включение и выключение функций Windows)
* Я использую Windows 7 на данный момент и не уверен, что именно путь. [GOOGLE: установка базовой аутентификации в IIS] должна закрыть вас.
Шаг 2.
Убедитесь, что на вашем сайте включена базовая аутентификация. Если вам нужно было установить это на предыдущем шаге, вам нужно убедиться, что вы reset обслуживаете IIS и что все пулы приложений фактически опустились.
Шаг 3.
(Примечание. Я использую MVC3 и считаю, что это должно работать в большинстве моделей, включая ASP.Net, без особых проблем).
В вашем проекте вам нужно будет добавить следующие классы:
public class ServicePrincipal : IPrincipal { // This answers the "What am I allowed to do" question
// In real life, this guy will contain all your user info
// and you can put what ever you like and retrieve it
// later via the HttpContext, on your application side.
// Some fun with casting will be required.
public static IPrincipal Default {
get {
return new ServicePrincipal {
Identity = new ServiceIdentity {
AuthenticationType = "Test",
IsAuthenticated = true,
Name = "Basic"
}
};
}
}
public IIdentity Identity { get; set; }
public bool IsInRole(string role) {
// If you want to use role based authorization
// e.g. [Authorize(Roles = "CoolPeople")]
// This is the place to do it and you can do
// anything from load info from a db or flat file
// or simple case statement...though that would
// be silly.
return true;
}
}
public class ServiceIdentity : IIdentity { // This answers the "Who Am I" Question
public string AuthenticationType { get; set; }
public bool IsAuthenticated { get; set; }
public string Name { get; set; }
}
public class ServiceModule : IHttpModule { // This is the module for IIS
public void Init(HttpApplication context) {
context.AuthenticateRequest += this.BasicAuthenticationRequest;
}
public void BasicAuthenticationRequest(object sender, EventArgs e) {
HttpApplication app = sender as HttpApplication;
if( !ServiceProvider.Authenticate(app.Context) ) {
// Total FAIL!
}
}
public void Dispose() {
// Clean up the mess, if needed.
}
}
public class ServiceProvider {
public static bool Authenticate( HttpContext context ) {
// For the example we are going to create a nothing user
// say he is awesome, pass him along through and be done.
// The heavy lifting of the auth process will go here
// in the real world.
HttpContext.Current.User = ServicePrincipal.Default;
return true;
}
}
Шаг 3a. [Править]
Здесь разные библиотеки, которые вы будете использовать
using System.Security.Principal;
using System.Web;
Просто хотел бросить их. Я ненавижу, когда люди оставляют их.:)
Шаг 4.
Добавьте в свою веб-конфигурацию следующее. Обратите внимание, что я включаю в себя структуру окружения, например тег "Конфигурация"... Это просто дорожная карта, если у вас уже есть тэг конфигурации, не добавляйте другого, или IIS расстраивается с вами.
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ServiceCredentialModule" type="{Namespace}.ServiceModule"/>
</modules>
</system.webServer>
<configuration>
Обратите внимание, что пространство имен в {Namespace}.ServiceModule - это пространство имен, которое вы кладете классы со стадии 3 в.
... и это в значительной степени.