我现在已经在这2天了.我使用的是WebAPI 2.2版,我使用的是CORS.此设置适用于服务器端,我可以从我的Web客户端服务器代码获取授权内容,但在我的ajax调用中未经授权.
这是我的配置:
Web API配置
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);
(我已经尝试过app.UseCors(CorsOptions.AllowAll)和config.EnableCors()的每个组合)
我的控制器属性:
[Authorize] [EnableCors("http://localhost:8080","*",SupportsCredentials = true)] [RoutePrefix("api/videos")] public class VideosController : ApiController...
Web客户端
Ajax电话:
$.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 });
最后但并非最不重要的是,我的标题.
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
开发人员工具和提琴手声称没有随请求发送的cookie.
解决方法
我相信你在这里混合了cookie身份验证和承载令牌,你没有在你的请求的Authorization标题中发送访问令牌,这就是你不断获得401的原因.
同样,您只需要使用application.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll)允许CORS;并从控制器属性甚至从配置中移除其他位置.
同样,您只需要使用application.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll)允许CORS;并从控制器属性甚至从配置中移除其他位置.
检查我的Repo here,我已经实现了CORS,前端也是AngularJS.它工作正常.对于此repo,开放式开发人员工具以及监视请求,这里也是live demo,您应该在看到HTTP get请求之前看到飞行前请求.
如果您只需要使用持有人令牌来保护您的API,那么我建议您阅读Token Based Authentication帖子