我正在尝试创建一个使用.Net ASP.Net WebAPI和KnockoutJs作为前端的演示项目。我创建了监听/ token帖子的控制器方法,并验证用户,并返回一个令牌。这是通过Knockout View Model的Ajax Post完成的。
此代码有效。但是,当我从webApi获得200返回(成功)时,我然后重定向到一个控制器方法,用[Authorize]装饰。那就是我打到401的地方 - 未经授权。
Login()
{
var data = {
username : this.login.emailAddress(),
password : this.login.password(),
RememberMe: this.login.rememberMe(),
grant_type: "password"
}
return $.ajax({
type: "POST",
data: data,
dataType: "json",
url: "/token",
contentType: "application/json"
}).done((reply) => {
window.location.href = "/Home/AnotherThing";
});
}
我认为问题是 - 我从/ token(登录)调用得到了回复,但是没有做任何事情。我不知道如何处理令牌。我愚蠢地认为OAuth会以某种方式将令牌放入我的标题中,并且它们会神奇地存在。我错了。
所以,我一直在寻找一个例子,然后我能找到的最好的是Here
但这意味着我将在每个视图模型上有很多重复的代码
提取物:
function ViewModel() {
var self = this;
var tokenKey = 'accessToken';
var RefTokenKey = 'refreshToken';
self.result = ko.observable();
self.user = ko.observable();
self.token = ko.observable();
self.refreshToken = ko.observable();
function showError(jqXHR) {
self.result(jqXHR.status + ': ' + jqXHR.statusText);
}
self.callApi = function () {
self.result('');
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: '/api/values',
headers: headers
}).done(function (data) {
self.result(data);
}).fail(showError);
}
self.callToken = function () {
self.result('');
var loginData = {
grant_type: 'password',
username: self.loginEmail(),
password: self.loginPassword()
};
$.ajax({
type: 'POST',
url: '/Token',
data: loginData
}).done(function (data) {
self.user(data.userName);
// Cache the access token in session storage.
sessionStorage.setItem(tokenKey, data.access_token);
var tkn = sessionStorage.getItem(tokenKey);
$("#tknKey").val(tkn);
}).fail(showError);
}
}
var app = new ViewModel();
ko.applyBindings(app);
这似乎是我所缺少的一部分:
sessionStorage.setItem(tokenKey, data.access_token);
var tkn = sessionStorage.getItem(tokenKey);
$("#tknKey").val(tkn);
我是否需要每个视图模型都有代码然后转到sessionStorage并获取令牌?
所以,这个:
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: '/api/values',
headers: headers
}).done(function (data) {
self.result(data);
}).fail(showError);
}
好像很多代码..这是正确的方法吗?
答案 0 :(得分:3)
好的,您可以做的是将持有者令牌附加到您的每个HTTP请求中。我假设你在那里使用jQuery?如果是这种情况,你可以leverage the beforeSend
config param。
提取可重用的方法,例如:
function onBeforeSend(xhr, settings) {
var token = sessionStorage.getItem(tokenKey);
if (token) {
xhr.setRequestHeader('Authorization', 'Bearer ' + token );
}
}
然后只需将该方法附加到需要令牌的每个$.ajax
调用中,如下所示:
$.ajax({
type: 'GET',
url: '/api/values',
headers: headers,
beforeSend: onBeforeSend
}).done(function (data) {
self.result(data);
}).fail(showError);
onBeforeSend
函数显然需要通过你的ajax调用来访问(我不是一个淘汰的人,所以我不知道它是否有任何构造,如服务,但如果没有,你可以命名它例如,为了避免使其成为一个全局函数,但您的代码组织由您决定。)
这样,您只需要为每个需要auth的请求添加beforeSend: onBeforeSend
位,这样可以避免不必要的代码重复。