No' Access-Control-Allow-Origin',仅在第一次通话时出错,但随后有效

时间:2015-02-11 14:29:44

标签: facebook asp.net-web-api cors

我有一个AngularJS应用程序试图使用我的Web Api进行身份验证。如果用户在我的数据库中不存在,则在第一次调用我的服务器时会收到以下错误,但是一旦用户存在于我的数据库中,则在后续调用同一方法时不会发生此错误。 (相关代码在底部)

请求的资源上没有“Access-Control-Allow-Origin”标头。因此,不允许原点“http://localhost:1378”访问。响应的HTTP状态代码为500。

逻辑的流程是:

  1. AngularJS在用户点击登录时使用Facebook进行身份验证
  2. App为我的服务器执行$ http.post,以获取auth / login传递其凭据
  3. 服务器轮询Facebook API以获取用户详细信息
  4. 如果用户存在,请更新其个人资料并验证身份
  5. 否则,创建新的会员用户,使用FB详细信息进行更新,然后使用auth'em
  6. 唯一不同的是,如果它们不存在于数据库中(即发生缺陷时),则login方法异步调用createUser方法然后返回数据。没有额外的外部电话。

    启用CORS的API启动方法:

    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错误的情况下工作。这真的困扰我,但效率低下,我很想知道一个更好的方法。

1 个答案:

答案 0 :(得分:1)

如果您正在使用angularjs,则可能需要查看satellizer。它使auth过程非常简单,并且有一些很棒的内置窗口弹出控件。

就Access-Control-Allow-Origin调用而言,它可能正在发生,因为您在一次调用中明确设置了标头而其他调用正在回退到默认的http提供程序?查看$http,看看提供这些默认值是否可以解决问题。