Autenticación de API web ASP.NET

122

Estoy buscando autenticar a un usuario desde una aplicación cliente mientras uso la API web ASP.NET . He visto todos los videos en el sitio y también he leído esta publicación en el foro .

Poner el [Authorize]atributo correctamente devuelve un 401 Unauthorizedestado. Sin embargo, necesito saber cómo permitir que un usuario inicie sesión en la API.

Quiero proporcionar las credenciales de usuario de una aplicación de Android a la API, hacer que el usuario inicie sesión y luego tener todas las llamadas API posteriores autenticadas previamente.

Mujtaba Hassan
fuente
Hola mujtaba ¿Pudiste implementar esto?
Vivek Chandraprakash
Primero use CORS para evitar golpes no deseados de otros dominios. Luego envíe una cookie de autenticación de formularios válida junto con la solicitud y finalmente autorice la solicitud por token. Esta combinación siempre hace que su API web sea segura y optimizada.
Majedur Rahaman el

Respuestas:

137

permitir que un usuario inicie sesión en la API

Debe enviar una cookie de autenticación de formularios válida junto con la solicitud. Esta cookie generalmente la envía el servidor cuando se autentica ( LogOnacción) llamando al [FormsAuthentication.SetAuthCookiemétodo (consulte MSDN ).

Entonces el cliente necesita realizar 2 pasos:

  1. Envíe una solicitud HTTP a una LogOnacción enviando el nombre de usuario y la contraseña. A su vez, esta acción llamará al FormsAuthentication.SetAuthCookiemétodo (en caso de que las credenciales sean válidas) que a su vez establecerá la cookie de autenticación de formularios en la respuesta.
  2. Envíe una solicitud HTTP a una [Authorize]acción protegida mediante el envío de la cookie de autenticación de formularios que recuperó en la primera solicitud.

Pongamos un ejemplo. Suponga que tiene 2 controladores API definidos en su aplicación web:

El primero responsable de manejar la autenticación:

public class AccountController : ApiController
{
    public bool Post(LogOnModel model)
    {
        if (model.Username == "john" && model.Password == "secret")
        {
            FormsAuthentication.SetAuthCookie(model.Username, false);
            return true;
        }

        return false;
    }
}

y el segundo que contiene acciones protegidas que solo los usuarios autorizados pueden ver:

[Authorize]
public class UsersController : ApiController
{
    public string Get()
    {
        return "This is a top secret material that only authorized users can see";
    }
}

Ahora podríamos escribir una aplicación cliente que consuma esta API. He aquí un ejemplo de aplicación de consola trivial (asegúrese de que ha instalado el Microsoft.AspNet.WebApi.Clienty Microsoft.Net.Httppaquetes NuGet):

using System;
using System.Net.Http;
using System.Threading;

class Program
{
    static void Main()
    {
        using (var httpClient = new HttpClient())
        {
            var response = httpClient.PostAsJsonAsync(
                "http://localhost:26845/api/account", 
                new { username = "john", password = "secret" }, 
                CancellationToken.None
            ).Result;
            response.EnsureSuccessStatusCode();

            bool success = response.Content.ReadAsAsync<bool>().Result;
            if (success)
            {
                var secret = httpClient.GetStringAsync("http://localhost:26845/api/users");
                Console.WriteLine(secret.Result);
            }
            else
            {
                Console.WriteLine("Sorry you provided wrong credentials");
            }
        }
    }
}

Y así es como se ven las 2 solicitudes HTTP en el cable:

Solicitud de autenticación:

POST /api/account HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost:26845
Content-Length: 39
Connection: Keep-Alive

{"username":"john","password":"secret"}

Respuesta de autenticación:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=REMOVED FOR BREVITY; path=/; HttpOnly
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 4
Connection: Close

true

Solicitud de datos protegidos:

GET /api/users HTTP/1.1
Host: localhost:26845
Cookie: .ASPXAUTH=REMOVED FOR BREVITY

Respuesta para datos protegidos:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 13 Jun 2012 13:24:41 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 66
Connection: Close

"This is a top secret material that only authorized users can see"
Darin Dimitrov
fuente
¿Va a mantener una sesión para la aplicación de Android?
Mujtaba Hassan
Entendí el punto, pero ¿puedes publicar un código de muestra para el segundo punto? Gracias por tu respuesta.
Mujtaba Hassan
2
Escribir un cliente HTTP de Android es un tema para otra pregunta. No está relacionado con ASP.NET MVC y ASP.NET MVC Web API, que es de lo que se trataba su pregunta. Le recomendaría que comience un nuevo hilo explícitamente etiquetado con Java y Android en el que pregunte cómo escribir un cliente HTTP que envíe solicitudes utilizando cookies.
Darin Dimitrov
En realidad, en la literatura de MVC4 WebApi, han escrito que WebAPI es el objetivo para clientes de terceros, especialmente clientes móviles (y por supuesto lo es). Digamos que tenemos un cliente de aplicación de escritorio, ¿puede publicar un fragmento de código simple por favor? Gracias
Mujtaba Hassan
2
También vea esta pregunta (y respuesta) sobre el uso de la autenticación básica HTTP: stackoverflow.com/questions/10987455/…
Jim Harte
12

Tomo Android como ejemplo.

public abstract class HttpHelper {

private final static String TAG = "HttpHelper";
private final static String API_URL = "http://your.url/api/";

private static CookieStore sCookieStore;

public static String invokePost(String action, List<NameValuePair> params) {
    try {
        String url = API_URL + action + "/";
        Log.d(TAG, "url is" + url);
        HttpPost httpPost = new HttpPost(url);
        if (params != null && params.size() > 0) {
            HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
            httpPost.setEntity(entity);
        }
        return invoke(httpPost);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokePost(String action) {
    return invokePost(action, null);
}

public static String invokeGet(String action, List<NameValuePair> params) {
    try {
        StringBuilder sb = new StringBuilder(API_URL);
        sb.append(action);
        if (params != null) {
            for (NameValuePair param : params) {
                sb.append("?");
                sb.append(param.getName());
                sb.append("=");
                sb.append(param.getValue());
            }
        }
        Log.d(TAG, "url is" + sb.toString());
        HttpGet httpGet = new HttpGet(sb.toString());
        return invoke(httpGet);
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }

    return null;
}

public static String invokeGet(String action) {
    return invokeGet(action, null);
}

private static String invoke(HttpUriRequest request)
        throws ClientProtocolException, IOException {
    String result = null;
    DefaultHttpClient httpClient = new DefaultHttpClient();

    // restore cookie
    if (sCookieStore != null) {
        httpClient.setCookieStore(sCookieStore);
    }

    HttpResponse response = httpClient.execute(request);

    StringBuilder builder = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            response.getEntity().getContent()));
    for (String s = reader.readLine(); s != null; s = reader.readLine()) {
        builder.append(s);
    }
    result = builder.toString();
    Log.d(TAG, "result is ( " + result + " )");

    // store cookie
    sCookieStore = ((AbstractHttpClient) httpClient).getCookieStore();
    return result;
}

Atención, por favor: i.localhost no se puede utilizar. El dispositivo Android parece localhost como host. ii. Si implementa la API web en IIS, se debe abrir la autenticación de formulario.

usuario2293998
fuente
0

Use este código y acceda a la base de datos

[HttpPost]
[Route("login")]
public IHttpActionResult Login(LoginRequest request)
{
       CheckModelState();
       ApiResponse<LoginApiResponse> response = new ApiResponse<LoginApiResponse>();
       LoginResponse user;
       var count = 0;
       RoleName roleName = new RoleName();
       using (var authManager = InspectorBusinessFacade.GetAuthManagerInstance())
       {
           user = authManager.Authenticate(request); 
       } reponse(ok) 
}
Sanila Salim
fuente