ASP.NET MVC – Indicación de autenticación HTTP

¿Es posible hacer que mi aplicación solicite un nombre de usuario y una contraseña que la solicite antes de mostrarla? Al igual que en la API de Twitter para obtener información sobre su cuenta:

http://twitter.com/account/verify_credentials.xml

Entonces, antes de renderizar la vista || archivo que le pide que inserte su nombre de usuario y contraseña, creo que esto se hace directamente en el servidor ya que la solicitud curl se basa en nombre de usuario: contraseña y así:

curl -u user:password http://twitter.com/account/verify_credentials.xml 

Como estoy tratando de construir una API siguiendo la misma estructura, me gustaría saber cómo puedo hacer esto en ASP.NET MVC C #. Ya he usado esto en ruby ​​rails y es bastante simple como:

 before_filter :authenticate def authenticate authenticate_or_request_with_http_basic do |username, password| username == "foo" && password == "bar" end 

No creo que el filtro [Autorizar] sea el mismo ya que creo que es solo una redirección, y lo redirecciona al Controlador interno de cuentas que se basa en la base de datos de cuentas, en este caso usaré otra base de datos, específicamente de una servicio web y hacer la validación después de enviar la información. Pero necesito la acción para requerir al usuario y pasar credenciales a petición suya.

Gracias por adelantado


ACTUALIZAR:

En realidad, para solicitar una página que requiera esta autenticación (es decir, Twitter) tendría que declarar esto en su solicitud

 request.Credentials = new NetworkCredential("username", "password"); 

Y esto reflejaría el nombre de usuario y la contraseña solicitados.

Por lo tanto, es exactamente lo mismo, pero desde el otro lado, si es posible proporcionar información a la solicitud de autenticación, ¿cómo puedo solicitar esta autenticación en la solicitud?

Así que cada vez que alguien intenta hacer una solicitud a mi aplicación, por ejemplo:

http: // myapplication / clients / verify_credentials

debería solicitar un nombre de usuario y una contraseña con el aviso del servidor para recuperar la información en curl, por ejemplo, sería como esto

 curl -u user:password http://myapplication/clients/verify_credentials 

Bueno, para requerir autenticación básica necesita devolver el código de estado 401. Pero al hacerlo, el módulo de autenticación actual ejecutará su controlador predeterminado no autorizado (para la autenticación de formularios, esto significa redirigir a la página de inicio de sesión).

Escribí ActionFilterAttribte para ver si puedo obtener el comportamiento que desea cuando no hay ningún módulo de autenticación instalado en 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(); } } } 

Y la acción del controlador:

 [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)); } 

Esa acción imprime con éxito el nombre de usuario y la contraseña que ingresé. Pero realmente dudo que sea la mejor manera de hacer esto. ¿No tienes más remedio que pedir el nombre de usuario y la contraseña de esta manera?

Realmente desea crear un servicio y no una aplicación web, en función de lo que he leído. Estoy adivinando aquí, pero creo que eligió ASP.NET MVC para aprovechar el enrutamiento y construir la URL de la manera que desee. Corrígeme si estoy equivocado.

En mi opinión, la mejor manera de resolver el problema que está teniendo es crear servicios web RESTful con WCF si está devolviendo datos. Este artículo debería ayudarte a comenzar si quieres seguir esta ruta.

De lo contrario, deberá ir más arriba en la stack para manejar la solicitud y autenticarla. Si este es el caso, puedo ayudar a proporcionar más información y código.

Modifiqué la respuesta de çağdaş para poner toda la lógica dentro de mi atributo personalizado de 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(); } } 

Se puede usar para poner en Basic Authentication un controlador completo:

 [BasicAuthenticationAttribute("your-username", "your-password", BasicRealm = "your-realm")] public class HomeController : BaseController { ... } 

o un ActionResult específico:

 public class HomeController : BaseController { [BasicAuthenticationAttribute("your-username", "your-password", BasicRealm = "your-realm")] public ActionResult Index() { ... } } 

NOTA : la implementación anterior requiere que el desarrollador inserte manualmente el nombre de usuario y la contraseña como parámetros necesarios de ActionFilter, pero puede ampliarse fácilmente para que admita cualquier mecanismo de autorización (MembershipProvider, ASP.NET Identity, base de usuarios personalizada en un DBMS o archivo externo, etc. ) eliminando el constructor personalizado y modificando el método IF de OnActionExecuting.

También puedes leer aquí para más información .

Esta es la forma en que me ha funcionado. Es un poco trabajo de pie, pero hará que IIS y MVC3 se comporten mucho más como todos los demás sistemas de autenticación de Basic Http, como Apache …

Paso 1.

Asegúrese de que esté instalada la “Autenticación básica” para IIS.

(Ejemplo: Panel de control -> Progtwigs y características -> Activar o desactivar las características de Windows)

* Estoy usando Windows 7 en este momento y no estoy seguro de la ruta exacta. [GOOGLE: instalar autenticación básica en IIS] debería acercarte.

Paso 2.

Asegúrese de que la Autenticación básica esté habilitada en su sitio. Si tuvo que instalar esto en el paso anterior, debe asegurarse de restablecer el servicio IIS y de que todos los grupos de aplicaciones se hayan desactivado.

Paso 3.

(Nota: estoy usando MVC3, y siento que esto debería funcionar en la mayoría de los modelos, incluyendo ASP.Net, sin mucho alboroto).
En su proyecto, deberá agregar las siguientes clases:

 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 // eg [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; } } 

Paso 3a. [editar]

Aquí están las diferentes libs que “usarás”

 using System.Security.Principal; using System.Web; 

Solo quería echarlos. Odio cuando la gente los deja fuera. 🙂

Etapa 4.

Agregue lo siguiente a su configuración web. Tenga en cuenta que incluyo la estructura circundante, por ejemplo, la etiqueta de “configuración” … Es solo una hoja de ruta, si ya tiene una etiqueta de “configuración”, no agregue la otra o IIS se enoja con usted.

        

Tenga en cuenta que el espacio de nombres en {Namespace} .ServiceModule es el espacio de nombres donde coloca las clases del paso 3.

… y eso es más o menos.