带有 CORS 和 Angular 的 .NET Web API 2 在第一篇文章中不起作用
Posted
技术标签:
【中文标题】带有 CORS 和 Angular 的 .NET Web API 2 在第一篇文章中不起作用【英文标题】:.NET Web API 2 with CORS and Angular Not Working on First Post 【发布时间】:2017-05-21 23:01:32 【问题描述】:我正在使用带有 Angular 1 和 Auth0 的 .Net ASP Web API V2。
通过 Auth0 初始登录后,我收到以下错误:
XMLHttpRequest 无法加载 localhost:3001/profile。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'localhost:62379'。响应的 HTTP 状态代码为 500。
如果我刷新我不再收到错误。如果我清除浏览器数据,我会再次收到错误,但刷新后会成功。
我在 API 配置中使用所需的 NUGET 包启用了 CORS。
我尝试了以下解决方案,因为我认为这是飞行前的问题:
1) 通过拦截请求在控制器上和全局处理 SELECT 动词。 http://www.jefclaes.be/2012/09/supporting-options-verb-in-aspnet-web.html
2) 将选择动词添加为控制器方法中接受的动词之一。
3) 我在这里找到了各种用于更改请求的答案。 ** 我的代表太低了,我无法分享链接。
等等
4) 使用特定来源而不是 *
控制器:
[Route("profile")]
[EnableCors(origins: "*", headers: "*", methods: "OPTIONS")]
public HttpResponseMessage Options()
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Headers.Add("Access-Control-Allow-Origin", "*");
resp.Headers.Add("Access-Control-Allow-Methods", "*");
return resp;
[Route("profile")]
[EnableCors(origins: "*", headers: "*", methods: "POST")]
[HttpPost]
public object Post([FromBody]dynamic data)
string email = null;
var b = new object();
try
**** Logic ****
catch (Exception ex)
**** Return Error ****
return b;
API 配置
public static class WebApiConfig
public static void Register(HttpConfiguration config)
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
// Web API configuration and services
config.EnableCors(cors);
var clientID = WebConfigurationManager.AppSettings["auth0:ClientId"];
var clientSecret = WebConfigurationManager.AppSettings["auth0:ClientSecret"];
config.MessageHandlers.Add(new JsonWebTokenValidationHandler()
Audience = clientID, // client id
SymmetricKey = clientSecret // client secret
);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/controller/id",
defaults: new id = RouteParameter.Optional
);
角度请求
function postLogin()
var loginPackage = [];
if (token === null) token = store.get('token');
if (store.get('profile') != null)
loginPackage = store.get('profile');
return $q(function(resolve, reject)
$http(
method: 'Post',
url: BASE + 'profile',
data: loginPackage,
crossDomain: true,
xhrFields:
withCredentials: true
,
contentType: 'application/json'
)
.success(function(data, status)
*** Logic ***
resolve(function()
resolve(true);
);
)
.error(function(data, status)
reject(function()
);
);
);
我想我可能已经看这个太久了,而忽略了一些相当简单的事情。
////**** 更新****////
回复:
HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcaWFteWFcRGVza3RvcFxOZXcgZm9sZGVyICgzKVx3ZWJhcGlcQXBpXHByb2ZpbGU=?=
X-Powered-By: ASP.NET
Date: Sun, 08 Jan 2017 00:17:26 GMT
Content-Length: 709
//* 更新 *///
使用 clean 浏览器缓存 REQUEST(失败)
POST /profile HTTP/1.1
Host: localhost:3001
Connection: keep-alive
Content-Length: 2372
Accept: application/json, text/plain, */*
Origin: http://localhost:62379
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Authorization: Bearer null
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:62379/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
我认为这可能是飞行前,但我的理解是使用 OPTIONS 动词而不是 POST 动词。
从外观上看,授权设置不正确。
Authorization: Bearer null
回应:
HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcaWFteWFcRGVza3RvcFxOZXcgZm9sZGVyICgzKVx3ZWJhcGlcQXBpXHByb2ZpbGU=?=
X-Powered-By: ASP.NET
Date: Sun, 08 Jan 2017 00:31:49 GMT
Content-Length: 709
之后立即发送第二个 Post 并且成功。这实际上是飞行前。
请求:
OPTIONS /profile HTTP/1.1
Host: localhost:3001
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:62379
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Access-Control-Request-Headers: authorization, content-type
Accept: */*
Referer: http://localhost:62379/index.html
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
以及回应:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/10.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: authorization,content-type
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcaWFteWFcRGVza3RvcFxOZXcgZm9sZGVyICgzKVx3ZWJhcGlcQXBpXHByb2ZpbGU=?=
X-Powered-By: ASP.NET
Date: Sun, 08 Jan 2017 00:34:43 GMT
Content-Length: 0
因此,我无法超越登录视图。加载屏幕出现错误。如果我再次刷新并登录,则没有错误。
请求:
POST /profile HTTP/1.1
Host: localhost:3001
Connection: keep-alive
Content-Length: 2367
Accept: application/json, text/plain, */*
Origin: http://localhost:62379
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3ltdC5hdXRoMC5jb20vIiwic3ViIjoiZmFjZWJvb2t8MTAxNTM4MjIxOTc4MTIyNTEiLCJhdWQiOiJWWDhHMFMyUWM5cUFjYnRrM09pMVZMa2NkWGxnWlBtZSIsImV4cCI6MTQ4Mzg3MTMyNywiaWF0IjoxNDgzODM1MzI3fQ.HBQcGC6aad2pLaq3nPuhojrFT2b6Usv64p97b-DCRCU
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:62379/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
授权字段现在具有令牌而不是空值:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3ltdC5hdXRoMC5jb20vIiwic3ViIjoiZmFjZWJvb2t8MTAxNTM4MjIxOTc4MTIyNTEiLCJhdWQiOiJWWDhHMFMyUWM5cUFjYnRrM09pMVZMa2NkWGxnWlBtZSIsImV4cCI6MTQ4Mzg3MTMyNywiaWF0IjoxNDgzODM1MzI3fQ.HBQcGC6aad2pLaq3nPuhojrFT2b6Usv64p97b-DCRCU
响应成功,登录继续。
令牌似乎只有在刷新后才注入。
我的 AUTH0 配置是:
authProvider.init(
domain: A0_DOMAIN,
clientID: A0_CLIENT,
callbackUrl: location.href,
loginState: 'out.login',
options:options
);
var refreshingToken = null;
jwtInterceptorProvider.tokenGetter = function(store, jwtHelper)
var token = store.get('token');
var refreshToken = store.get('refreshToken');
if (token)
if (!jwtHelper.isTokenExpired(token))
return store.get('token');
else
if (refreshingToken === null)
refreshingToken = auth.refreshIdToken(refreshToken)
.then(function(idToken)
store.set('token', idToken);
return idToken;
)
.finally(function()
refreshingToken = null;
);
;
jwtOptionsProvider.config(
whiteListedDomains: ['localhost','https://www.ymtechno.com','https://www.ymtechno.com/_api','https://ymtechno.com/_api']
);
$httpProvider.interceptors.push('jwtInterceptor');
)
.run(function($rootScope, auth, store, jwtHelper, $location)
var refreshingToken = null;
$rootScope.$on('$locationChangeStart',
function()
var token = store.get('token');
var refreshToken = store.get('refreshToken');
if (token)
if (!jwtHelper.isTokenExpired(token))
auth.authenticate(store.get('profile'), token);
else
if (refreshingToken === null)
refreshingToken = auth.refreshIdToken(refreshToken)
.then(function(idToken)
store.set('token', idToken);
return idToken;
)
.finally(function()
refreshingToken = null;
);
return refreshingToken;
else
$location.path('login');
);
auth.hookEvents();
【问题讨论】:
我不会编程.net
,但让我印象深刻的是你有[AcceptVerbs("OPTIONS")]
,但你的EnableCors
说允许*
方法。您的 Web 框架似乎覆盖了您尝试手动添加的标头。您应该让您的框架定义这些标头。检查您的注释。
我认为这是正确的,但是在清除我的缓存后,我又遇到了同样的错误。一旦我得到第一个错误,我就可以登录没有问题。
删除这个[AcceptVerbs("OPTIONS")]
请提供原始 http 响应
现在包含响应。
【参考方案1】:
经过调查,我发现拦截器在重新启动应用程序之前没有将令牌放入 auth 标头中。这被读取为 CORS 错误,因为请求不符合访问 API 的条件。令牌值未定义。
可以在此处找到有关注入器和标头的更深入的线程:
Set HTTP header for one request
如果您遇到相同的问题,这是一个有用的参考。
【讨论】:
以上是关于带有 CORS 和 Angular 的 .NET Web API 2 在第一篇文章中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Angular 7 .net 核心 2.2 WebApi Windows 身份验证 CORS
.net mvc angular应用程序中的CORS问题[关闭]
在带有 Angular 的 Spring Boot 中启用了 Cors,但仍然出现 cors 错误
ASP.NET Core:带有 OPTIONS 异常的 Windows 身份验证(CORS 预检)