Authentication: 强制刷新页面进行授权
Authentication: forced to refresh page to be authorised
我正在使用 this blog 中的代码为我的 angular 应用制作身份验证模块。
我有一个测试页面,其中包括一个登录表单、一个提交按钮和一个将查询受限路由的 "profile" 按钮。
<div class="container-fluid" ng-controller="AuthCtrl as auth">
<input type="text" ng-model="auth.user.username">
<input type="text" ng-model="auth.user.password">
<button ng-click="auth.login(auth.user)">LOGIN</button>
<button ng-click="auth.profile()">PROFILE</button>
</div>
登录后查询的限制路由定义为:
const authenticate = expressJwt({
secret: SECRET
});
app.get('/me', authenticate, function(req, res) {
res.status(200).json(req.user);
});
登录正常。我收到一个放入 sessionStorage 的令牌。
当我点击个人资料按钮(向 /me 发出请求)时,出现未经授权的错误。
如果我刷新页面并再次单击个人资料,我会得到预期的行为。 (/me returns用户数据没有错误)
如果我在那之后手动删除令牌,我仍然可以访问 /me 直到我刷新页面。
这是我的服务:
function loginService($http) {
this.login = function(user) {
return $http.post('/auth', user).then(
function(response) {
return response.data;
},
function(response) {
return response;
});
};
this.profile = function() {
return $http.get('/me').then(
function(response) {
return response.data;
},
function(response) {
return response;
});
};
}
angular
.module('app')
.service('loginService', loginService);
这是我的 httpProvider 控制器:
function AuthCtrl($window, $http, loginService) {
this.user = {username: "", password: ""};
this.login = function(user) {
loginService.login(user).then(function(data) {
$window.sessionStorage.token = data.token;
});
};
this.profile = function() {
loginService.profile().then(function(data) {
console.log(data);
});
};
}
function config($httpProvider, $windowProvider) {
var window = $windowProvider.$get();
if(window.sessionStorage.token) {
var token = window.sessionStorage.token;
$httpProvider.defaults.headers.common.Authorization = 'Bearer ' + token;
}
};
angular
.module('app')
.config(config)
.controller('AuthCtrl', AuthCtrl);
问题可能来自将令牌存储在 sessionStorage 中还是来自 http 提供商?
最终我会实施 secure cookie method 但我想在继续之前解决这个问题。
我终于发现它是为了 $httpProvider
代码而来的。
function config($httpProvider, $windowProvider) {
var window = $windowProvider.$get();
if(window.sessionStorage.token) {
var token = window.sessionStorage.token;
$httpProvider.defaults.headers.common.Authorization = 'Bearer ' + token;
}
};
提供商选项仅在应用加载期间设置了一次。
重新加载页面将重新运行配置代码并按预期进入 if(window.sessionStorage.token)
条件。
为了使这个配置动态化,我必须像这样创建一个 interceptor(工厂):
function config($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
};
function authInterceptor($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
},
responseError: function (rejection) {
if (rejection.status === 401) {
console.log("not authorised");
}
return $q.reject(rejection);
}
};
};
angular
.module('app')
.config(config)
.controller('AuthCtrl', AuthCtrl)
.factory('authInterceptor', authInterceptor);
我正在使用 this blog 中的代码为我的 angular 应用制作身份验证模块。
我有一个测试页面,其中包括一个登录表单、一个提交按钮和一个将查询受限路由的 "profile" 按钮。
<div class="container-fluid" ng-controller="AuthCtrl as auth">
<input type="text" ng-model="auth.user.username">
<input type="text" ng-model="auth.user.password">
<button ng-click="auth.login(auth.user)">LOGIN</button>
<button ng-click="auth.profile()">PROFILE</button>
</div>
登录后查询的限制路由定义为:
const authenticate = expressJwt({
secret: SECRET
});
app.get('/me', authenticate, function(req, res) {
res.status(200).json(req.user);
});
登录正常。我收到一个放入 sessionStorage 的令牌。 当我点击个人资料按钮(向 /me 发出请求)时,出现未经授权的错误。
如果我刷新页面并再次单击个人资料,我会得到预期的行为。 (/me returns用户数据没有错误)
如果我在那之后手动删除令牌,我仍然可以访问 /me 直到我刷新页面。
这是我的服务:
function loginService($http) {
this.login = function(user) {
return $http.post('/auth', user).then(
function(response) {
return response.data;
},
function(response) {
return response;
});
};
this.profile = function() {
return $http.get('/me').then(
function(response) {
return response.data;
},
function(response) {
return response;
});
};
}
angular
.module('app')
.service('loginService', loginService);
这是我的 httpProvider 控制器:
function AuthCtrl($window, $http, loginService) {
this.user = {username: "", password: ""};
this.login = function(user) {
loginService.login(user).then(function(data) {
$window.sessionStorage.token = data.token;
});
};
this.profile = function() {
loginService.profile().then(function(data) {
console.log(data);
});
};
}
function config($httpProvider, $windowProvider) {
var window = $windowProvider.$get();
if(window.sessionStorage.token) {
var token = window.sessionStorage.token;
$httpProvider.defaults.headers.common.Authorization = 'Bearer ' + token;
}
};
angular
.module('app')
.config(config)
.controller('AuthCtrl', AuthCtrl);
问题可能来自将令牌存储在 sessionStorage 中还是来自 http 提供商?
最终我会实施 secure cookie method 但我想在继续之前解决这个问题。
我终于发现它是为了 $httpProvider
代码而来的。
function config($httpProvider, $windowProvider) {
var window = $windowProvider.$get();
if(window.sessionStorage.token) {
var token = window.sessionStorage.token;
$httpProvider.defaults.headers.common.Authorization = 'Bearer ' + token;
}
};
提供商选项仅在应用加载期间设置了一次。
重新加载页面将重新运行配置代码并按预期进入 if(window.sessionStorage.token)
条件。
为了使这个配置动态化,我必须像这样创建一个 interceptor(工厂):
function config($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
};
function authInterceptor($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
},
responseError: function (rejection) {
if (rejection.status === 401) {
console.log("not authorised");
}
return $q.reject(rejection);
}
};
};
angular
.module('app')
.config(config)
.controller('AuthCtrl', AuthCtrl)
.factory('authInterceptor', authInterceptor);