Uwierzytelnianie interfejsu API sieci Web ASP.NET

122

Chcę uwierzytelnić użytkownika z aplikacji klienckiej podczas korzystania z interfejsu API sieci Web ASP.NET . Obejrzałem wszystkie filmy na stronie, a także przeczytałem ten post na forum .

Umieszczenie [Authorize]atrybutu poprawnie zwraca 401 Unauthorizedstatus. Muszę jednak wiedzieć, jak zezwolić użytkownikowi na zalogowanie się do interfejsu API.

Chcę podać poświadczenia użytkownika z aplikacji na Androida do interfejsu API, zalogować się, a następnie wstępnie uwierzytelnić wszystkie kolejne wywołania interfejsu API.

Mujtaba Hassan
źródło
Cześć Mujtaba. Czy byłeś w stanie to zaimplementować?
Vivek Chandraprakash
Najpierw użyj CORS, aby zapobiec niechcianym trafieniom z innych domen. Następnie wyślij prawidłowy plik cookie uwierzytelniania za pomocą formularzy wraz z żądaniem i ostatecznie autoryzuj żądanie za pomocą tokena. Ta kombinacja zawsze zapewnia bezpieczeństwo i optymalizację interfejsu API sieci Web.
Majedur Rahaman

Odpowiedzi:

137

pozwalają użytkownikowi zalogować się do API

Wraz z żądaniem należy wysłać prawidłowy plik cookie do uwierzytelniania za pomocą formularzy. Ten plik cookie jest zwykle wysyłany przez serwer podczas uwierzytelniania ( LogOnakcji) poprzez wywołanie [FormsAuthentication.SetAuthCookiemetody (patrz MSDN ).

Klient musi więc wykonać 2 kroki:

  1. Wyślij żądanie HTTP do LogOnakcji, wysyłając nazwę użytkownika i hasło. Ta akcja z kolei wywoła FormsAuthentication.SetAuthCookiemetodę (w przypadku, gdy poświadczenia są prawidłowe), co z kolei ustawi plik cookie uwierzytelniania formularzy w odpowiedzi.
  2. Wyślij żądanie HTTP do [Authorize]akcji chronionej, wysyłając plik cookie uwierzytelniania formularzy, który został pobrany w pierwszym żądaniu.

Weźmy przykład. Załóżmy, że masz 2 kontrolery API zdefiniowane w swojej aplikacji internetowej:

Pierwszy odpowiedzialny za obsługę uwierzytelniania:

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

a druga zawiera chronione akcje, które mogą zobaczyć tylko upoważnieni użytkownicy:

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

Teraz możemy napisać aplikację kliencką korzystającą z tego API. Oto trywialny przykład aplikacji konsolowej (upewnij się, że masz zainstalowane pakiety Microsoft.AspNet.WebApi.Clienti Microsoft.Net.HttpNuGet):

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

A tak wyglądają 2 żądania HTTP w sieci:

Żądanie uwierzytelnienia:

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"}

Odpowiedź uwierzytelniająca:

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

Wniosek o chronione dane:

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

Odpowiedź na chronione dane:

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
źródło
Czy będzie utrzymywać sesję dla aplikacji na Androida?
Mujtaba Hassan
Mam rację, ale czy możesz przesłać przykładowy kod dla drugiego punktu. Dziękuję za odpowiedź.
Mujtaba Hassan
2
Pisanie klienta HTTP dla Androida to temat na inne pytanie. Nie ma związku z ASP.NET MVC i ASP.NET MVC Web API, o co chodziło w Twoim pytaniu. Zalecałbym rozpoczęcie nowego wątku z jawnym tagowaniem w Javie i Androidzie, w którym pytasz, jak napisać klienta HTTP, który wysyła żądania za pomocą plików cookie.
Darin Dimitrov
Właściwie w literaturze MVC4 WebApi napisali, że WebAPI jest celem dla klientów zewnętrznych, zwłaszcza klientów mobilnych (i oczywiście tak jest). Powiedzmy, że mamy klienta aplikacji komputerowej, czy możesz opublikować prosty fragment kodu. Dzięki
Mujtaba Hassan
2
Zobacz także to pytanie (i odpowiedź) dotyczące korzystania z podstawowego uwierzytelniania HTTP: stackoverflow.com/questions/10987455/…
Jim Harte
12

Jako przykład biorę androida.

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

Uwaga, proszę : i.localhost nie może być używany. Urządzenie z Androidem wygląda jak lokalny host. ii. w przypadku wdrażania internetowego interfejsu API w usługach IIS należy otworzyć uwierzytelnianie formularza.

user2293998
źródło
0

Użyj tego kodu i uzyskaj dostęp do bazy danych

[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
źródło