Angular,对预检请求的响应

时间:2016-05-09 11:20:59

标签: javascript angularjs http authentication

我有一个拦截器,可以处理我控制器上的所有请求。我有一个实现刷新令牌的后端Web API,但当我尝试刷新令牌并继续发出请求时,我得到“对预检请求的响应未通过访问控制检查:否'访问控制 - 允许-Origin'标题出现在请求的资源上。因此,不允许原点'http://localhost'访问。响应的HTTP状态代码为400.“令牌请求给了我{“error”:“invalid_clientId”,“error_description”:“应该发送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;
            });
    }
}]);

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我已经设法解决了我自己的问题,在拦截器上我注入了authService函数并重置了localstorage访问,然后我添加了" ALLOW OPTION"要在我的网络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
        }
    };
}]);

<强>的AuthenticationService

 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);
        }