否 'Access-Control-Allow-Origin',仅在第一次调用时出错,但随后有效
No 'Access-Control-Allow-Origin', only errors on first call but works subsequently
我有一个 AngularJS 应用程序正在尝试使用我的 Web Api 进行身份验证。如果用户在我的数据库中不存在,我在第一次调用我的服务器时收到以下错误,但是一旦用户存在于我的数据库中,后续调用相同的方法时就不会发生。 (相关代码在底部)
请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源“http://localhost:1378”。响应具有 HTTP 状态代码 500。
逻辑流程是:
- AngularJS 当用户点击登录时使用 Facebook 进行授权
- 应用程序向我的服务器执行 $http.post 以 auth/login 传递他们的凭据
- 服务器轮询 Facebook API 以获取用户详细信息
- 如果用户存在,更新他们的个人资料并授权他们
- 否则,创建新的会员用户,更新 FB 详细信息,并授权他们
如果它们不存在于数据库中(即出现缺陷时),唯一不同的是登录方法异步调用 createUser 方法,然后调用 returns 数据。没有进行额外的外部调用。
API启用CORS的启动方法:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
ConfigureOAuth(app);
app_start.WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
API 控制器:
[Route("Login")]
[HttpPost]
[AllowAnonymous]
public async Task<FacebookUserModel> Login(FacebookUserRequest user)
{
FacebookUserModel fbUser = new FacebookUserModel();
// Build FacebookUser object
try {
// Grab basic user details
string profileRequestUri = "https://graph.facebook.com/" + user.fbID + "?access_token=" + user.access_token;
HttpWebRequest profileRequest = (HttpWebRequest)WebRequest.Create(profileRequestUri);
profileRequest.Method = WebRequestMethods.Http.Get;
profileRequest.Accept = "application/json";
HttpWebResponse profileResponse = (HttpWebResponse)profileRequest.GetResponse();
Stream profileResponseStream = profileResponse.GetResponseStream();
StreamReader profileStreamReader = new StreamReader(profileResponseStream);
fbUser = JsonConvert.DeserializeObject<FacebookUserModel>(profileStreamReader.ReadToEnd());
} catch (Exception) ...
try {
// Grab profile picture
string pictureRequestUri = "https://graph.facebook.com/" + user.fbID + "/picture";
HttpWebRequest pictureRequest = (HttpWebRequest)WebRequest.Create(pictureRequestUri);
pictureRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse pictureResponse = (HttpWebResponse)pictureRequest.GetResponse();
fbUser.profilePictureUri = pictureResponse.ResponseUri.ToString();
} catch (Exception) ...
// If user exists, change password to new token and return)
if(userExists)
{
try {
IdentityUser identityUser = _repo.FindUser(ID, pass).Result;
FacebookUserModel dbUser = db.FacebookUserObjects.First(u => u.identityUserID == identityUser.Id);
db.Entry(dbUser).CurrentValues.SetValues(fbUser);
db.SaveChangesAsync();
fbUser.identityUserID = identityUser.Id;
return fbUser;
}
catch (Exception e)
{ return null; }
}
// Else, create the new user using same scheme
else
{
UserModel newUser = new UserModel
{
UserName = ID,
Password = pass,
ConfirmPassword = pass
};
// Create user in Identity & linked Facebook record
createUser(newUser, fbUser);
return fbUser;
}
}
private async void createUser(UserModel newUser, FacebookUserModel fbUser)
{
IdentityResult result = await _repo.RegisterUser(newUser);
var identityUser = await _repo.FindUser(newUser.UserName, newUser.Password);
fbUser.identityUserID = identityUser.Id;
db.FacebookUserObjects.Add(fbUser);
db.SaveChangesAsync();
}
AngularJS 调用我的服务器:
var _login = function (fbID, fbToken) {
$http.post(serviceBase + 'auth/login', { "fbID": fbID, "access_token": fbToken }).then(function (response) {
var data = "grant_type=password&username=" + fbID + "&password=" + pass;
$http.post(serviceBase + 'auth/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.success(function (tokenResponse) {
authServiceFactory.bearerToken = tokenResponse.access_token;
})
.error(function (err) {
console.log("token error:", err);
});
authServiceFactory.userObject = response.data;
window.localStorage['userObject'] = JSON.stringify(authServiceFactory.userObject);
})
};
为什么我只会在第一次调用时收到 No 'Access-Control-Allow-Origin' 错误,而在后续调用时却不会?
更新
我有一个可行的解决方法,但我不太喜欢。问题仅在从我的登录控制器调用第二种方法时出现,因此如果我将该代码向上移动到登录控制器而不是辅助方法,它可以在没有 CORS 错误的情况下工作。这确实让我很困扰,而且效率低下,我很想知道更好的解决方法。
如果您正在使用 angularjs,您可能想查看 satellizer。它使身份验证过程非常简单,并且有一些很棒的内置 window 弹出控件。
就 Access-Control-Allow-Origin 调用而言,它可能会发生,因为您在一个调用上明确设置了 headers,而其他调用则回退到默认的 http 提供程序?查看 $http 看看提供这些默认值是否可以解决它。
我有一个 AngularJS 应用程序正在尝试使用我的 Web Api 进行身份验证。如果用户在我的数据库中不存在,我在第一次调用我的服务器时收到以下错误,但是一旦用户存在于我的数据库中,后续调用相同的方法时就不会发生。 (相关代码在底部)
请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源“http://localhost:1378”。响应具有 HTTP 状态代码 500。
逻辑流程是:
- AngularJS 当用户点击登录时使用 Facebook 进行授权
- 应用程序向我的服务器执行 $http.post 以 auth/login 传递他们的凭据
- 服务器轮询 Facebook API 以获取用户详细信息
- 如果用户存在,更新他们的个人资料并授权他们
- 否则,创建新的会员用户,更新 FB 详细信息,并授权他们
如果它们不存在于数据库中(即出现缺陷时),唯一不同的是登录方法异步调用 createUser 方法,然后调用 returns 数据。没有进行额外的外部调用。
API启用CORS的启动方法:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
ConfigureOAuth(app);
app_start.WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
API 控制器:
[Route("Login")]
[HttpPost]
[AllowAnonymous]
public async Task<FacebookUserModel> Login(FacebookUserRequest user)
{
FacebookUserModel fbUser = new FacebookUserModel();
// Build FacebookUser object
try {
// Grab basic user details
string profileRequestUri = "https://graph.facebook.com/" + user.fbID + "?access_token=" + user.access_token;
HttpWebRequest profileRequest = (HttpWebRequest)WebRequest.Create(profileRequestUri);
profileRequest.Method = WebRequestMethods.Http.Get;
profileRequest.Accept = "application/json";
HttpWebResponse profileResponse = (HttpWebResponse)profileRequest.GetResponse();
Stream profileResponseStream = profileResponse.GetResponseStream();
StreamReader profileStreamReader = new StreamReader(profileResponseStream);
fbUser = JsonConvert.DeserializeObject<FacebookUserModel>(profileStreamReader.ReadToEnd());
} catch (Exception) ...
try {
// Grab profile picture
string pictureRequestUri = "https://graph.facebook.com/" + user.fbID + "/picture";
HttpWebRequest pictureRequest = (HttpWebRequest)WebRequest.Create(pictureRequestUri);
pictureRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse pictureResponse = (HttpWebResponse)pictureRequest.GetResponse();
fbUser.profilePictureUri = pictureResponse.ResponseUri.ToString();
} catch (Exception) ...
// If user exists, change password to new token and return)
if(userExists)
{
try {
IdentityUser identityUser = _repo.FindUser(ID, pass).Result;
FacebookUserModel dbUser = db.FacebookUserObjects.First(u => u.identityUserID == identityUser.Id);
db.Entry(dbUser).CurrentValues.SetValues(fbUser);
db.SaveChangesAsync();
fbUser.identityUserID = identityUser.Id;
return fbUser;
}
catch (Exception e)
{ return null; }
}
// Else, create the new user using same scheme
else
{
UserModel newUser = new UserModel
{
UserName = ID,
Password = pass,
ConfirmPassword = pass
};
// Create user in Identity & linked Facebook record
createUser(newUser, fbUser);
return fbUser;
}
}
private async void createUser(UserModel newUser, FacebookUserModel fbUser)
{
IdentityResult result = await _repo.RegisterUser(newUser);
var identityUser = await _repo.FindUser(newUser.UserName, newUser.Password);
fbUser.identityUserID = identityUser.Id;
db.FacebookUserObjects.Add(fbUser);
db.SaveChangesAsync();
}
AngularJS 调用我的服务器:
var _login = function (fbID, fbToken) {
$http.post(serviceBase + 'auth/login', { "fbID": fbID, "access_token": fbToken }).then(function (response) {
var data = "grant_type=password&username=" + fbID + "&password=" + pass;
$http.post(serviceBase + 'auth/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.success(function (tokenResponse) {
authServiceFactory.bearerToken = tokenResponse.access_token;
})
.error(function (err) {
console.log("token error:", err);
});
authServiceFactory.userObject = response.data;
window.localStorage['userObject'] = JSON.stringify(authServiceFactory.userObject);
})
};
为什么我只会在第一次调用时收到 No 'Access-Control-Allow-Origin' 错误,而在后续调用时却不会?
更新
我有一个可行的解决方法,但我不太喜欢。问题仅在从我的登录控制器调用第二种方法时出现,因此如果我将该代码向上移动到登录控制器而不是辅助方法,它可以在没有 CORS 错误的情况下工作。这确实让我很困扰,而且效率低下,我很想知道更好的解决方法。
如果您正在使用 angularjs,您可能想查看 satellizer。它使身份验证过程非常简单,并且有一些很棒的内置 window 弹出控件。
就 Access-Control-Allow-Origin 调用而言,它可能会发生,因为您在一个调用上明确设置了 headers,而其他调用则回退到默认的 http 提供程序?查看 $http 看看提供这些默认值是否可以解决它。