Angular,对飞行前请求的响应

Angular, Response to Preflight Request

本文关键字:响应 请求 飞行前 Angular      更新时间:2023-09-26

我有一个拦截器,可以处理控制器上的所有请求。我有一个后端web API,它实现刷新令牌,但当我尝试刷新令牌并继续进行请求时,我会得到"对预飞请求的响应未通过访问控制检查:请求的资源上不存在"access-control-Allow-Origin"头。Origin"http://localhost因此不允许访问。响应的HTTP状态代码为400。"令牌请求给了我{"error":"invalid_clientId","errordescription":"应该发送clientId。"}

拦截器:

var appInterceptors = angular.module("auth-Interceptor", ["ngRoute", "angular-loading-bar"]);
/* ==== Bearer token headers configuration ==== */
appInterceptors.factory("authentication-interceptor", ["$q", "$injector", "$rootScope", "$location", "cfpLoadingBar", function ($q, $injector, $rootScope, $location, cfpLoadingBar) {
    var inFlightAuthRequest = null;
    var deferred = $q.defer();
    return {
        // On request success
        request: function (config) {
            config.headers = config.headers || {};
            if ($rootScope.globals.accessToken != null) {
                config.headers.Authorization = 'Bearer ' + $rootScope.globals.accessToken;
            }
            // Return the config or wrap it in a promise if blank.
            return config || $q.when(config);
        },
        requestError: function (rejection) {
            debugger; //return debugger for more info
            return rejection;
        },
        responseError: function (rejection) {
            debugger;
            if (rejection.status === 401) {
                var refreshToken = window.localStorage.getItem("refreshToken");    //log the user in if there is an refresh token
                $injector.get("$http").post(
                        $rootScope.globals.apiPath + "/accessControl/token",
                        { client_id: "id", grant_type: "refresh_token", refresh_token: refreshToken },
                        { 'Content-Type': 'application/x-www-form-urlencoded' }
                    )
                    .then(function (data) {
                        inflightAuthRequest = null;
                        if (data.access_token != undefined && data.refresh_token != undefined) {
                            window.localStorage.setItem("refreshToken", data.refresh_token);
                            window.localStorage.setItem("accessToken", data.access_token);
                            window.localStorage.setItem("rememberMe", true);
                            window.localStorage.setItem("time_expires_in", data.expires_in);
                            $injector.get("$http")(rejection.config).then(function (resp) {
                                deferred.resolve(resp);
                            }, function (resp) {
                                deferred.reject();
                            });
                        } else {
                            deferred.reject();
                        }
                        return $q.reject(rejection);
                    }, function (response) {
                        deferred.reject();
                        authService.clear();
                        $injector.get("$state").go('/login');
                        return;
                    });
                return deferred.promise;
            }
        }
    };
}]);
appInterceptors.config(["$httpProvider", function ($httpProvider) {
    $httpProvider.interceptors.push("authentication-interceptor");
}]);

服务:

jobManagerApp.factory("authenticationService", ["$rootScope", "$http", "$location", function ($rootScope, $http, $location) {
    return {
        Login: function (username, password) {
            return $http({
                url: $rootScope.globals.apiPath + "/accessControl/token",
                method: 'POST',
                data: "userName=" + encodeURIComponent(username) +
                      "&password=" + encodeURIComponent(password) +
                      "&Scope=" + "website" +
                     "&grant_type=password" +
                     "&client_id=id",
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            });
        },
        RefreshToken: function (refreshtoken) {
            return $http({
                url: $rootScope.globals.apiPath + "/accessControl/token",
                method: 'POST',
                data: "client_id=" +
                      "&grant_type=refresh_token" +
                      "&refresh_token=" + refreshtoken,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            });
        },
        LogOut: function () {
            return $http({
                url: $rootScope.globals.apiPath + "/accessControl/logout",
                method: "POST"
            });
        },
        DoLogin: function (data, rememberMe) {
            //save the tokens
            if (rememberMe == true) {
                window.localStorage.setItem("refreshToken", data.refresh_token);
                window.localStorage.setItem("accessToken", data.access_token);
                window.localStorage.setItem("rememberMe", true);
            } else {
                window.localStorage.removeItem("refreshToken");
                window.localStorage.removeItem("accessToken");
            }
            //set the global values for user
            $rootScope.globals.accessToken = data.access_token;
            $rootScope.globals.refreshToken = data.refresh_token;
            //hide the menu items for which the users does not have access rights
            $rootScope.HideMenuItems();
            //navigate to the page where the user originally wanted to go (returnLocation) or to the default page
            var gotoLocation = $rootScope.globals.returnToLocation;
            if (gotoLocation != "") {
                $location.path(gotoLocation);
                $rootScope.globals.returnToLocation = "";
            } else {
                //go to default page
                $location.path("/home");
            }
            //set the logged in value only after the navigation has taken place as it is linked to the ng-show/hide of the toolbar and menu
            $rootScope.globals.isLoggedIn = true;
        }
    };
}]);

登录:

jobManagerApp.controller("loginController", ["$scope", "$rootScope", "$location", "authenticationService", function ($scope, $rootScope, $location, authenticationService) {
    $scope.LoginButtonDisabled = false;
    $scope.LogonName = null;
    $scope.Password = null;
    $scope.Error = "";
    $scope.Version = ($rootScope.globals.version.indexOf("-") == -1) ? $rootScope.globals.version : $rootScope.globals.version.substring(0, $rootScope.globals.version.indexOf("-"));
    $scope.Login = function () {
        $scope.LoginButtonDisabled = true;
        if ($scope.LogonName !== null && $scope.Password !== null) {
            //attempt login
            authenticationService.Login($scope.LogonName, $scope.Password)
                .success(function (data) {
                    $scope.LoginButtonDisabled = false;
                    if (data.access_token != undefined) {
                        //Time Expires
                        window.localStorage.setItem("time_expires_in", data.expires_in);
                        //Time user logged in
                        window.localStorage.setItem("time_logged_in", new Date().getTime());
                        //do the actual login
                        authenticationService.DoLogin(data, $scope.RememberMe);
                    }
                    else if (data.error_description != undefined) {
                        $scope.Error = data.error_description;
                    }
                    else {
                        $scope.Error = "Unexpected error occurred!";
                    }
                })
                .error(function (data, status, headers, config) {
                    $rootScope.globals.accessToken = null;
                    window.localStorage.removeItem("accessToken");
                    window.localStorage.removeItem("refreshToken");
                    $scope.LoginButtonDisabled = false;
                });
        } else {
            $scope.Error = "Enter a username and password!";
            $scope.LoginButtonDisabled = false;
        }        
    };
    var accessToken = window.localStorage.getItem("accessToken");     //log the user in if there is an access token
    var refreshToken = window.localStorage.getItem("refreshToken");    //log the user in if there is an refresh token
    var time_expires = window.localStorage.getItem("time_expires_in");     //Time token expires
    var time_logged_in = window.localStorage.getItem("time_logged_in");     //Time user logged in
    var time = new Date().getTime();     //CurrentTime
    var tokenExpired;    //variable to be used to setExpired 
    if (((time / 1000) - (time_logged_in / 1000)) >= time_expires) {
        tokenExpired = true;
    } else {
        tokenExpired = false;
    }
    //Log test
    console.log("Time left: " + (time_expires - ((time / 1000) - (time_logged_in / 1000))));
    console.log(refreshToken);
    //login
    if (accessToken != null && tokenExpired == false && refreshToken != null) {
        $rootScope.globals.accessToken = accessToken; //set this for the auth-interceptor to do its work
        $rootScope.globals.showLoading = true;
        $rootScope.globals.showLoading = false;
        var data = {
            access_token: accessToken,
            expires_in: time_expires,
            refresh_token: refreshToken
        };
        authenticationService.DoLogin(data, true);
        //authenticationService.GetAuthenticationProperties().success(function (data) {
        //    $rootScope.globals.showLoading = false;
        //    data.access_token = accessToken;
        //    authenticationService.DoLogin(data, true);
        //}).error(function () {
        //    $rootScope.globals.showLoading = false;
        //});
    } else if (refreshToken != null) {
        //request a new access token
        authenticationService.RefreshToken(refreshToken)
            .success(function (data) {
                if (data.access_token != undefined && data.refresh_token != undefined) {
                    $rootScope.globals.accessToken = data.access_token; //set this for the auth-interceptor to do its work
                    $rootScope.globals.refreshToken = data.refresh_token //Set the new refresh token 
                    $rootScope.globals.showLoading = true;  
                    $rootScope.globals.showLoading = false;
                    var data = {
                        access_token: data.access_token,
                        refresh_token: data.refresh_token,
                        expires_in: data.expires_in
                    };
                    //Renew the time logged in and the time time_expires
                    //Time Expires
                    window.localStorage.setItem("time_expires_in", data.expires_in);
                    //Time user logged in
                    window.localStorage.setItem("time_logged_in", new Date().getTime());
                    //Set the access token 
                    tokenExpired = false //renew to false;
                    authenticationService.DoLogin(data, true);
                }
            })
            .error(function (data, status, headers, config) {
                $rootScope.globals.accessToken = null;
                window.localStorage.removeItem("accessToken");
                window.localStorage.removeItem("refreshToken");
                $scope.LoginButtonDisabled = false;
            });
    }
}]);

任何帮助都将不胜感激。

我已经设法解决了我自己的问题,在拦截器上我注入了authService函数并重置了本地存储访问,然后我添加了和"ALLOW OPTION"用于在我的web API上解决的选项请求:

拦截器

appInterceptors.factory("authentication-interceptor", ["$q", "$injector", "$rootScope", "$location", "cfpLoadingBar", function ($q, $injector, $rootScope, $location, cfpLoadingBar) {
    return {
        // On request success
        request: function (config) {
            config.headers = config.headers || {};
            if ($rootScope.globals.accessToken != null) {
                config.headers.Authorization = 'Bearer ' + $rootScope.globals.accessToken;
            }
            // Return the config or wrap it in a promise if blank.
            return config || $q.when(config);
        },
        requestError: function (rejection) {
            debugger;
            return rejection;
        },
        responseError: function (response) {
            // error - was it 401 or something else?
            if (response.status === 401) {
                var deferred = $q.defer(); // defer until we can re-request a new token
                var accessToken = window.localStorage.getItem("accessToken");
                var refreshtoken = window.localStorage.getItem("refreshToken");
                // Get a new token... (cannot inject $http directly as will cause a circular ref)
                $injector.get("authenticationService").RefreshToken(refreshtoken).then(function (loginResponse) {
                        if (loginResponse) {    
                        console.log(loginResponse);
                        $rootScope.globals.accessToken = loginResponse.data.access_token; // we have a new acces token - set at $rootScope
                        $rootScope.globals.refreshToken = loginResponse.data.refresh_token; // we have a new refresh token - set at $rootScope
                        //Update the headers
                        window.localStorage.setItem("accessToken", loginResponse.data.access_token);
                        window.localStorage.setItem("refreshToken", loginResponse.data.refresh_token);
                        window.localStorage.setItem("rememberMe", true);
                        //Time Expires
                        window.localStorage.setItem("time_expires_in", loginResponse.data.expires_in);
                        //Time user logged in
                        window.localStorage.setItem("time_logged_in", new Date().getTime());
                        // now let's retry the original request - transformRequest in .run() below will add the new OAuth token
                        $injector.get("authenticationService").ResolveDeferred(response.config).then(function (defResp) {
                            // we have a successful response - resolve it using deferred
                            deferred.resolve(defResp);
                        }, function (defResp) {
                            deferred.reject(); // something went wrong
                        });
                    } else {
                        deferred.reject(); // login.json didn't give us data
                    }
                }, function (response) {
                    deferred.reject(); // token retry failed, redirect so user can login again
                    $location.path('/login');
                    return;
                });
                return deferred.promise; // return the deferred promise
            }
            return $q.reject(response); // not a recoverable error
        }
    };
}]);

身份验证服务

 RefreshToken: function (refreshtoken) {
            return $http({
                url: $rootScope.globals.apiPath + "/accessControl/token",
                method: 'POST',
                datatype: 'jsonp',
                data: "client_id=id" +
                      "&grant_type=refresh_token" +
                      "&refresh_token=" + refreshtoken,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            });
        },
        LogOut: function () {
            return $http({
                url: $rootScope.apiPath + "/acess/logout",
                method: "POST"
            });
        },
        ResolveDeferred: function (config) {
            return $http(config);
        },

API

 public override Task MatchEndpoint(OAuthMatchEndpointContext context)
        {
            if (context.IsTokenEndpoint && context.Request.Method == "OPTIONS")
            {
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "authorization" });
                context.RequestCompleted();
                return Task.FromResult(0);
            }
            return base.MatchEndpoint(context);
        }