Javascript $location.path不会加载相关页,如果其承诺在身份验证拦截期间被拒绝
我在AngularJS应用程序中进行身份验证拦截时遇到问题 为了说明这一点,我制作了一个非常简化的应用程序版本,其中包含一个登录页面(路径Javascript $location.path不会加载相关页,如果其承诺在身份验证拦截期间被拒绝,javascript,angularjs,ajax,Javascript,Angularjs,Ajax,我在AngularJS应用程序中进行身份验证拦截时遇到问题 为了说明这一点,我制作了一个非常简化的应用程序版本,其中包含一个登录页面(路径/login)和一个Hello World页面(路径//code>),您必须登录才能看到。在路由提供者解析期间,Hello World页面上显示的问候语是通过Ajax获取的,只有提供了有效的访问令牌,此操作才会成功 这就是我的经历: 用户尝试访问位于/的Hello World页面 在可以加载Hello World页面控制器之前,应该从服务器获取问候语文本–因为
/login
)和一个Hello World页面(路径//code>),您必须登录才能看到。在路由提供者解析期间,Hello World页面上显示的问候语是通过Ajax获取的,只有提供了有效的访问令牌,此操作才会成功
这就是我的经历:
用户尝试访问位于/
的Hello World页面
在可以加载Hello World页面控制器之前,应该从服务器获取问候语文本–因为还不知道访问令牌,服务器会以状态401
进行响应。这在身份验证拦截器的responseError
中被捕获,用户从该拦截器重定向到位于/login
的登录页面
在登录页面,系统将提示用户输入凭据,直到服务器上的auth API满意并返回有效的访问令牌为止–此访问令牌将存储以供以后使用,用户将重定向到位于/
的Hello World页面
登录页面保持可见,而不是使用新获得的访问令牌重新蚀刻问候语文本,然后显示Hello World页面–地址栏中的URL更新为提及/
,而不是/login
。
为什么与/
相关的页面未加载?该承诺先前已被拒绝,但是否应不再尝试解决该承诺?
或者我在这里尝试的方式是无法将promise内容与auth拦截混合使用?
控制台屏幕截图:
档案:
index.html
:
试验
auth.html
:
请登录
用户名:
密码:
提交
{{message}}
auth.js
:
var auth=angular.module(“Test.auth”,[“ngRoute”]);
auth.factory(“AuthInterceptor”,函数($q,$location,UserInfo){
返回{
请求:函数(配置){
if(config.url.indexOf(“/api/”)==0){
config.headers[“AJAX”]=true;//=>这样服务器就不会在响应中包含WWW身份验证头,并且可以避免浏览器身份验证弹出窗口
如果(!config.headers.Authorization)config.headers[“ACCESS-TOKEN”]=UserInfo.accessToken();
}
返回配置;
},
responseError:函数(响应){
如果($location.path()!=“/login”){
log(“responseError-401请求失败,转到/login”);
UserInfo.forget();
$location.path(“/login”);
}
返回$q.reject(响应);
}
};
}).config(函数($httpProvider){
$httpProvider.interceptors.push('AuthInterceptor');
});
auth.service(“auth”,函数($rootScope,$location,$http,UserInfo){
this.logIn=函数(凭据){
$http.get(“/api/v1/auth/login”{
标题:{
授权:“基本”+btoa(凭证.用户名+:“+凭证.密码)
}
})
.成功(职能(负责人){
UserInfo.create(主体);
log(“登录-转到/”;
$location.path(“/”);
})
.错误(函数(){
$rootScope.$broadcast(“登录失败”);
});
};
});
身份验证服务(“UserInfo”,函数($window){
this.init=函数(){
如果(!$window.sessionStorage[“userInfo”])这个.forget();
else this.userInfo=JSON.parse($window.sessionStorage[“userInfo”]);
};
this.create=函数(主体){
this.userInfo={
用户名:principal.userName,
accessToken:principal.accessToken
};
$window.sessionStorage[“userInfo”]=JSON.stringify(this.userInfo);
};
this.forget=函数(){
this.userInfo=null;
$window.sessionStorage[“userInfo”]=null;
};
this.accessToken=函数(){
返回this.userInfo==null?null:this.userInfo.accessToken;
};
});
auth.controller(“AuthCtrl”,函数($scope,auth){
$scope.logIn=Auth.logIn;
$scope.$on(“登录失败”,函数(){
$scope.message=“请提供有效凭据。”;
});
});
hello.html
:
{{hello}
hello.js
:
var hello=angular.module(“HelloApp”、“ngRoute”、“Test.auth”);
hello.run(函数(UserInfo){
UserInfo.init();
});
hello.config(函数($routeProvider){
$routeProvider
.when(“/login”{
templateUrl:“/test/auth.html”,
控制器:“AuthCtrl”
})
.当(“/”时{
templateUrl:“/test/hello.html”,
控制器:“HelloCtrl”,
决心:{
hello:函数(hello){
log(“resolve.hello”);
回复你好。承诺;
}
}
})
.否则({
重定向至:“/”
});
});
hello.service(“hello”,函数($http){
this.promise=$http.get(“/api/v1/utils/hello”)
.然后(功能(响应){
console.log(“获取的”“+response.data+”);
返回响应数据;
});
});
hello.controller(“HelloCtrl”,函数($scope,hello){
$scope.hello=hello;
});
这就是我认为正在发生的事情!以下代码:
if ($location.path() !== "/login") {
console.log("responseError - request failed with 401, go to /login");
UserInfo.forget();
$location.path("/login");
}
return $q.reject(response);
当$location.path()
等于“\”
如果位置路径为“\”
则需要解决承诺问题。是的,问题是承诺只能评估一次,这是通过设计实现的。显而易见的解决方法是将promise
属性更改为每次调用时都会返回新的promise
的函数。因此,您可以执行以下操作:
hello.service(“hello”,函数($http){
this.promiseBuilder=函数(){
返回$http.post(“/api/v1/utils/hello”)
.然后(功能(响应){
$routeProvider
.when("/", {
templateUrl: "/test/hello.html",
controller: "HelloCtrl",
resolve: {
hello: function (Hello) {
console.log("resolve.hello");
return Hello.promiseBuilder();
}
}
})