rod*_*ogq 5 cors asp.net-web-api angularjs preflight typescript
我有一个 angularjs HTML 客户端到一个 WebApi 项目。当我通过 POSTMAN 或其他 REST 客户端测试 API 时,似乎一切正常。
当我开始使用带有 angularjs 客户端的浏览器时,浏览器总是使用 OPTIONS 启动预检请求。在那里,我的 WebAPI 总是回答 400 Bad Request - 我仍处于“/api/token”阶段。
我已经将我的 WebAPI 项目的每一个点附加到调试器。我还根据 SO 中关于如何启用 CORS 的几个答案更改了几点。其中一些我已经尝试过:更改 web.config 以在每个请求上添加启用 cors 的标头,将 cors 添加到 WebApi 启动中,在“/token”覆盖的函数中启用 cors。
这是我得到的原因:
Angularjs TypeScript 调用“/api/token”:
logIn = (userName: string, userPassword: string): ng.IPromise<void> => {
var postData = {
"grant_type": "password",
"client_id": this.appConfiguration.ClientId,
"client_secret": this.appConfiguration.ClientSecret,
"username": userName,
"password": userPassword
};
return this.$http.post<models.LoggedUserModel>('http://local.web.api/api/token', $.param(postData), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then((result) => {
this.localStorageService.set('Auth', result);
this.goHome(true);
}).catch((error) => {
console.warn(error);
});
}
Run Code Online (Sandbox Code Playgroud)
这是在我的 WebApi 上调用的唯一函数:
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// handle cors requests
if (!string.IsNullOrEmpty(context.OwinContext.Request.Headers.Get("Origin")))
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
}
try
{
// retrieve clientId and clientSecret from request body
string clientId;
string clientSecret;
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
// here it comes our application specific security code....
}
else
{
// this is part of enabling CORS..
if (context.Request.Method.ToUpper() == "OPTIONS")
{
// it returns OK to preflight requests having an empty body
context.Validated();
}
}
}
finally
{
// log stuff...
}
}
Run Code Online (Sandbox Code Playgroud)
如果我只留下 OWIN Cors 的东西,添加标题并调用“context.Validated()”,一切都会继续下去。这是我得到的:
Firefox Network Tab:
--------------------
Request URL: http://local.web.api/api/token
Request method: OPTIONS
Remote address: 127.0.0.1:80
Status code: 400 Bad Request
Version: HTTP/1.1
Request headers:
----------------
Host: local.web.api
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.7,pt-BR;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization
Origin: http://local.web.client
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Response headers:
-----------------
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Tue, 22 Dec 2015 15:24:23 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Run Code Online (Sandbox Code Playgroud)
我真的很感激一些关于去哪里的想法。这对我来说是全新的,我确实操作过其他一些 WebApi 项目 + angularjs。
好吧,这很糟糕,但我发现了问题。我在 angularjs 上使用 http 拦截器,它会自动检查登录用户并在需要时添加Authorization带有令牌的标头Bearer。问题是我做错了。
我在对象中创建了一个新属性config,bypassToken作为布尔值,这将是添加或不添加标题的标志Authorization。删除它实际上修复了代码。不知道为什么,但现在分析请求,我可以看到所有标头实际上都按预期发送:其中Content-Type第一个案例没有正确填写。奇怪的是,AngularJS 没有发出任何警告。
// http auth interceptor
angularApplication.factory('httpAuthInterceptor', ['$rootScope', '$injector', '$location', ($rootScope, $injector, $location): ng.IHttpInterceptor => {
var $q: ng.IQService = $injector.get('$q');
var localStorageService: ng.local.storage.ILocalStorageService = $injector.get('localStorageService');
return {
request: (config: ng.IRequestConfig): ng.IRequestConfig => {
// check if headers are present
config.headers = config.headers || {};
// the error was here! I was trying to add properties to config that I think angular was not expecting
// removing this line solved the issue
// if (!config.bypassToken) {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if (loggedUserInfo) {
config.headers['Authorization'] = 'Bearer ' + loggedUserInfo.access_token;
}
return config;
},
responseError: (rejection) => {
// check if user is logged in
var loggedUserInfo = localStorageService.get<models.LoggedUserInfoModel>('Auth');
if ((rejection.status === 401) && (loggedUserInfo)) {
// if so, then the user must login againd
localStorageService.remove('Auth');
$location.path('/home');
console.error(rejection);
}
return $q.reject(rejection);
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
我感谢您的帮助。我只是在此处发布此内容以防有人遇到类似问题。不要弄乱物体config!
| 归档时间: |
|
| 查看次数: |
2678 次 |
| 最近记录: |