2014-10-08 24 views
8

Od 2 dni drapie mnie po głowie. Używam WebAPI wersji 2.2 i używam CORS. Ta konfiguracja działa po stronie serwera, mogę uzyskać autoryzowaną zawartość z mojego kodu serwera klienta WWW, ale otrzymuję nieautoryzowane wywołania ajaxowe.401 Nieautoryzowane przy wysyłaniu żądania ajax do api internetowej

Oto moja konfiguracja:

Web API Config

WebApiConfig:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 

     // Web API configuration and services 
     // Configure Web API to use only bearer token authentication. 
     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 
     config.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie)); 

     //enable cors 
     config.EnableCors(); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

     config.Filters.Add(new ValidationActionFilter()); 
    } 
} 

Startup.Auth.cs:

// Configure the db context and user manager to use a single instance per request 
     app.CreatePerOwinContext(UserContext<ApplicationUser>.Create); 
     app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 

     // Enable the application to use a cookie to store information for the signed in user 
     // and to use a cookie to temporarily store information about a user logging in with a third party login provider 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
      { 
       AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
       CookieHttpOnly = true, 
       CookieName = "Outpour.Api.Auth" 
      } 
     ); 

     //app.UseCors(CorsOptions.AllowAll); 
     //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

     // Configure the application for OAuth based flow 
     PublicClientId = "self"; 
     OAuthOptions = new OAuthAuthorizationServerOptions 
     { 
      TokenEndpointPath = new PathString("/Token"), 
      Provider = new ApplicationOAuthProvider(PublicClientId), 
      AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
      AllowInsecureHttp = true 
     }; 

     // Enable the application to use bearer tokens to authenticate users 
     app.UseOAuthBearerTokens(OAuthOptions); 

(próbowałem każdy połączenie appuseCors (CorsOptions.AllowAll) a nd config.EnableCors())

mojego kontrolera atrybut:

[Authorize] 
[EnableCors("http://localhost:8080", "*", "*", SupportsCredentials = true)] 
[RoutePrefix("api/videos")] 
public class VideosController : ApiController... 

Web Client

Ajax Call: Stworzenie

$.ajaxPrefilter(function (options, originalOptions, jqXHR) { 
      options.crossDomain = { 
       crossDomain: true 
      }; 
      options.xhrFields = { 
       withCredentials: true 
      }; 
     }); 

     function ajaxGetVideoResolutionList() { 
      var request = { 
       type: "GET", 
       dataType: "json", 
       timeout: Outpour.ajaxTimeOut, 
       url: Outpour.apiRoot + "/videos/resolutions" 
      }; 
      $.ajax(request).done(onAjaxSuccess).fail(onAjaxError); 

Cookie:

var result = await WebApiService.Instance.AuthenticateAsync<SignInResult>(model.Email, model.Password); 

      FormsAuthentication.SetAuthCookie(result.AccessToken, model.RememberMe); 

      var claims = new[] 
      { 
       new Claim(ClaimTypes.Name, result.UserName), //Name is the default name claim type, and UserName is the one known also in Web API. 
       new Claim(ClaimTypes.NameIdentifier, result.UserName) //If you want to use User.Identity.GetUserId in Web API, you need a NameIdentifier claim. 
      }; 

      var authTicket = new AuthenticationTicket(new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie), new AuthenticationProperties 
      { 
       ExpiresUtc = result.Expires, 
       IsPersistent = model.RememberMe, 
       IssuedUtc = result.Issued, 
       RedirectUri = redirectUrl 
      }); 

      byte[] userData = DataSerializers.Ticket.Serialize(authTicket); 

      byte[] protectedData = MachineKey.Protect(userData, new[] { "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware", DefaultAuthenticationTypes.ApplicationCookie, "v1" }); 

      string protectedText = TextEncodings.Base64Url.Encode(protectedData); 

      Response.Cookies.Add(new HttpCookie("Outpour.Api.Auth") 
      { 
       HttpOnly = true, 
       Expires = result.Expires.UtcDateTime, 
       Value = protectedText 
      }); 

I na koniec moje nagłówki.

Remote Address:127.0.0.1:8888 
Request URL:http://127.0.0.1/api/videos/resolutions 
Request Method:GET 
Status Code:401 Unauthorized 

**Request Headersview source** 
Accept:application/json, text/javascript, */*; q=0.01 
Accept-Encoding:gzip,deflate,sdch 
Accept-Language:en-US,en;q=0.8 
Cache-Control:no-cache 
Host:127.0.0.1 
Origin:http://localhost:8080 
Pragma:no-cache 
Proxy-Connection:keep-alive 
Referer:http://localhost:8080/video/upload 
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36 

**Response Headersview source** 
Access-Control-Allow-Credentials:true 
Access-Control-Allow-Origin:http://localhost:8080 
Cache-Control:no-cache 
Content-Length:61 
Content-Type:application/json; charset=utf-8 
Date:Wed, 08 Oct 2014 04:01:19 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
WWW-Authenticate:Bearer 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

Narzędzia programistyczne i skrzypce twierdzą, że nie wysłano żadnych plików cookie z żądaniem.

Odpowiedz

3

wierzę jesteś mieszanie między uwierzytelniania cookie i żetonów na okaziciela Tutaj nie wysyłasz tokenu dostępu w nagłówku Authorization ze swoim wniosku, że jest to powód, dla którego wciąż otrzymujesz 401. Musisz tylko pozwolić CORS używając application.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); i usunąć go, skąd z atrybutów kontrolnych, nawet z konfiguracji.

Sprawdź mój Repo here, w którym zaimplementowałem CORS, a przednim końcem jest również AngularJS. działa poprawnie. Oto live demo również dla tego repo, otwartych narzędzi programistycznych i monitorowania żądań, powinieneś zobaczyć prośbę przed lotem, zanim zobaczysz swoje żądanie HTTP get.

Jeśli trzeba tylko chronić swoje API za pomocą tokenów okaziciela to polecam do zapoznania Token Based Authentication słupek

+0

Mam ten sam problem, ale nie używam WebAPI jako gospodarz zasobów, ale NancyFX. Wszystko jest znalezione, jeśli wywołane z loków, ale nie z aplikacji AngularJS. Token punkt końcowy jest w porządku, ale jeśli chodzi o GET dla trasy dostarczonej przez Nancy, ASP Net Authentication odrzuca preflight OPTION z 401. Nie mam pojęcia, jak przezwyciężyć to. Ponadto nie jestem pewien, czy repozytorium pasuje do wersji demo: repo używa identyfikatora klienta w żądaniu tokena, oczywiście nie demo. Nie związane, ale wskazanie, że obie wersje są różne. – decades

0

Może to być spowodowane tym, że interfejs API użytkownika nie znajduje się na podanym adresie URL jako aplikacja wywołująca. Twój adres URL jest API: http://127.0.0.1/ (ignorując ścieżkę folderu - co nie ma znaczenia)

..ale jesteś wzywającą go od http://127.0.0.1:8888 liczony jako odrębnej stronie jako port jest inny. Ponieważ przeglądarka uważa, że ​​strona jest inna, nie wyśle ​​pliku cookie.

Czy próbowałeś przetestować go ze strony hostowanej pod tym samym adresem URL co interfejs API (z tym samym portem)?

Co najważniejsze: Sprawdź, czy możesz zobaczyć plik cookie wysyłany przez Fiddlera.

Można również znaleźć więcej istotnych informacji o coraz to zadziałało on this answer

Powiązane problemy