android - Autenticación de la API web de ASP.NET
authentication asp.net-web-api (3)
Estoy buscando autenticar a un usuario desde una aplicación cliente mientras uso ASP.NET Web API . He visto todos los videos en el sitio y también he leído esta publicación en el foro .
Al colocar el atributo [Authorize]
correctamente se devuelve un estado 401 Unauthorized
. Sin embargo, necesito saber cómo permitir que un usuario inicie sesión en la API.
Deseo proporcionar credenciales de usuario desde una aplicación de Android a la API, obtener el inicio de sesión del usuario y, luego, autenticar previamente todas las llamadas subsiguientes a la API.
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 al autenticar (acción LogOn
) llamando al método [FormsAuthentication.SetAuthCookie
(vea MSDN ).
Entonces el cliente necesita realizar 2 pasos:
- Envíe una solicitud HTTP a una acción
LogOn
enviando el nombre de usuario y la contraseña. Por turnos, esta acción llamará al métodoFormsAuthentication.SetAuthCookie
(en caso de que las credenciales sean válidas) que, a su vez, configurará la cookie de autenticación de formularios en la respuesta. - Envíe una solicitud HTTP a una acción protegida
[Authorize]
enviando a lo largo de la cookie de autenticación de formularios que recuperó en la primera solicitud.
Tomemos un ejemplo. Supongamos 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 consumiendo esta API. Aquí hay un ejemplo de aplicación de consola trivial (asegúrese de haber instalado los paquetes Microsoft.AspNet.WebApi.Client
y Microsoft.Net.Http
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"
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 puede ser utilizado. El dispositivo Android mira localhost como el propio host. ii. Si implementa la API web en IIS, se debe abrir la autenticación de formulario.
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)
}