2012-10-22 16 views
13

Nota prawna: Zacznę od stwierdzenia, że ​​jestem nowy w MVC4 + Web Api + Web Services ogólnie + JQuery. Mogę atakować to pod niewłaściwym kątem.Równolegle uwierzytelnianie podstawowe i formularzy za pomocą interfejsu ASP.NET Web API

Próbuję utworzyć aplikację Web MVC + Web API w języku C# dla platformy .NET 4 w celu wdrożenia na platformie Azure. Interfejs API będzie używany przez klientów mobilnych (iOS, przy użyciu pakietu RestKit).

Aplikacja internetowa MVC będzie stosunkowo prosta. Chcielibyśmy skorzystać z uwierzytelniania formularzy dla niego i SimpleMembership - które osiągnęliśmy i działa dobrze.

Będziemy używać metod Web API ze skryptów JQuery (Knockout) do wypełniania fragmentów stron internetowych. Dlatego oczekujemy, że JQuery użyje tej samej tożsamości uwierzytelnianej przez Uwierzytelnianie za pomocą formularzy.

Jednak pomysł jest taki, że Web Api może być wywoływany bezpośrednio przez klientów mobilnych. Brak uwierzytelnień formularzy dla tych.

Szukaliśmy Thinktecture Identity Model (http://nuget.org/packages/Thinktecture.IdentityModelhttps://github.com/thinktecture/Thinktecture.IdentityModel.40). Dodaliśmy programy obsługi BasicAuth i AcessKey do konfiguracji i działa (zobacz poniższy kod).

Podczas próby uzyskania dostępu do webapi bez uwierzytelnienia przeglądarka wyświetla podstawowe okno dialogowe uwierzytelniania i działa zgodnie z oczekiwaniami.

"Problem" polega na tym, że gdy jesteś już zalogowany przy użyciu uwierzytelniania za pomocą formularzy i próbujesz wywołać metodę Web Api, nadal uzyskujesz okno dialogowe Basic Authentication. Innymi słowy, Thinktecture IdentityModel wydaje się zignorować w pełni uwierzytelnianie formularzy.

Moje pytania są następujące:

  1. Czy moje oczekiwania są prawidłowe? że po przeprowadzeniu uwierzytelniania formularzy nie powinienem robić nic więcej, aby skrypty JQuery itp. uzyskiwały dostęp do interfejsu Web API z tej samej sesji użytkownika przeglądarki.
  2. Jak to naprawić?
  3. Jeśli moje oczekiwania nie są prawidłowe; jak to ma działać? tj: jak dokonać uwierzytelnienia skryptów JQuery?

Wiem, że w Stackoverflow jest mnóstwo podobnych pytań, szczerze mówiąc wyglądałem dużo, widziałem filmy itp., Ale albo brakuje mi czegoś oczywistego, albo nie ma jasnej dokumentacji o tym dla kogoś nowego w technologie.

Doceniam pomoc. Dzięki.

public static AuthenticationConfiguration CreateConfiguration() 
{ 
var config = new AuthenticationConfiguration 
     { 
      DefaultAuthenticationScheme = "Basic", 
      EnableSessionToken = true, 
      SetNoRedirectMarker = true 
     };    

config.AddBasicAuthentication((userName, password) => userName == password, retainPassword: false); 
config.AddAccessKey(token => 
     { 
      if (ObfuscatingComparer.IsEqual(token, "accesskey123")) 
      { 
       return Principal.Create("Custom", 
        new Claim("customerid", "123"), 
        new Claim("email", "[email protected]")); 
      } 

      return null; 
     }, AuthenticationOptions.ForQueryString("key")); 

Odpowiedz

6

Oto rozwiązanie tego problemu, które wymyśliłem wcześniej.

Uwaga: To rozwiązanie nie obejmuje Thinktecture Identity Model.

Mam abstrakcyjną klasę BasicAuthenticationHandler, która jest procedurą obsługi delegowania. Możesz pobrać ten moduł obsługi, instalując najnowszą stację roboczą WebAPIDoodle NuGet package.

Możesz podać podpowiedź do tego podstawowego podstawowego programu do obsługi uwierzytelniania, aby wyłączyć proces uwierzytelniania, jeśli żądanie zostało już uwierzytelnione (np. Przez auth).Niestandardowy teleskopowa, że ​​trzeba się rejestrować będzie wyglądać jak poniżej:

public class MyApplicationAuthHandler : BasicAuthenticationHandler { 

    public MyApplicationAuthHandler() 
     : base(suppressIfAlreadyAuthenticated: true) { } 

    protected override IPrincipal AuthenticateUser(
     HttpRequestMessage request, 
     string username, 
     string password, 
     CancellationToken cancellationToken) { 

     //this method will be called only if the request 
     //is not authanticated. 

     //If you are using forms auth, this won't be called 
     //as you will be authed by the forms auth bofore you hit here 
     //and Thread.CurrentPrincipal would be populated. 

     //If you aren't authed: 
     //Do you auth here and send back an IPrincipal 
     //instance as I do below. 

     var membershipService = (IMembershipService)request 
      .GetDependencyScope() 
      .GetService(typeof(IMembershipService)); 

     var validUserCtx = membershipService 
      .ValidateUser(username, password); 

     return validUserCtx.Principal; 
    } 

    protected override void HandleUnauthenticatedRequest(UnauthenticatedRequestContext context) { 

     // Do nothing here. The Autharization 
     // will be handled by the AuthorizeAttribute. 
    } 
} 

W końcowym etapie, trzeba będzie zastosować System.Web.Http.AuthorizeAttribute (nie System.Web.Mvc.AuthorizeAttribute) do kontrolerów i metod działania, aby dać zezwolenie dla konkretnych ról i użytkowników.

Mam nadzieję, że pomoże to rozwiązać Twój problem.

+0

Witam, jest dobrze. Skąd jednak pochodzi interfejs "IMembershipService"? (nie wydaje się częścią WebAPIDoongle ani standardowego MVC .NET4). Zauważ, że twoja klasa działa, chciałbym, aby ta sama klasa obsługiwała również klawisze API, ale wierzę, że mogę dodać tę funkcję. Moim głównym problemem jest teraz, jak używać klasy "WebSecurity" do sprawdzania poprawności użytkownika względem bazy danych i zwracania dyrektora (mogę zrobić WebSecurity.Login, ale to jest kiepskie). – rufo

+0

BTW: podczas testowania z przeglądarki (przeglądarki Chrome) przeglądarka nie wymusza podstawowego uwierzytelniania, jeśli użytkownik nie jest zalogowany. Chociaż nie jest to konieczne dla moich klientów mobilnych, jest to wygodne do testowania. Też to sprawdzę. – rufo

+0

@rufo IMembershipService to moja własna implementacja. Położyłem to tam, żebyś wpadł na pomysł. Możesz zastąpić to za pomocą własnego imp. – tugberk

Powiązane problemy