我可以在响应 headers 中将不记名令牌传递给 Angular JS 应用程序吗?
Can I pass a bearer token to an Angular JS app in the response headers?
出于各种原因,我需要使用服务器技术,在本例中 ASP.Net 来呈现我的 Angular JS 应用程序。因此,当用户请求索引页面时,请求将通过 ASP.Net 管道,该管道将为应用程序提供脚本、视图等服务。
我需要在应用程序中获取不记名令牌,以便它可以调用各种 Web API 服务。
从安全角度来看,在响应 header 中将不记名令牌传递给用户浏览器是否可以接受?然后当 Angular JS 应用程序启动时,它将从 header 中读取值并将其放入本地存储以供后续 API 请求使用。
用户流...
- 用户转到 members.domain.com,其中 he/she 未通过身份验证。
- 用户重定向到 OAuth 提供商。
- 用户通过提供商进行身份验证。
- 然后用户被重定向回 members.domain.com。用户现已通过身份验证并且他们有一个 cookie。
- 初始应用程序页面通过 MVC 管道呈现。根据用户声明(例如 role="recruiter" 等)检查声明并使用菜单选项(等)呈现 UI。
这会获取在用户浏览器上呈现的初始应用程序,并根据用户声明创建菜单选项。
现在缺少的部分是将不记名令牌放入浏览器,可用于调用各种 APIs。
更新:我正在根据您更新的问题完全更改我的答案。
你想做的事对我来说实际上听起来不错。听起来您要在 client-side.
上检查 JWT 作为您的 Bearer 令牌
为此,您需要执行以下两项操作之一:
如果您希望通过使用 cookie 使您的应用程序更 'secure',您可以在后端创建一个路由(/me
或类似的东西),当请求,returns 所有当前登录用户的个人数据(他们的声明,以及呈现您的 UI 所需的任何内容)。当 Angular 应用程序启动时,它可以向该页面发出请求,将通过已设置的 cookie 进行身份验证,并且只 return 前端需要的任何数据进行渲染。
如果您想在纯 JS 中做所有事情,冒着更容易受到 XSS 攻击的风险,那么与其将用户的 Bearer 令牌存储在 cookie 中,不如将其存储在 HTML5本地存储。这样,您的 Angular 应用程序可以直接在浏览器中通过 Javascript 访问令牌以呈现页面。这可能会提供更快的性能,但这意味着任何可以在您的域上 运行 恶意 JS 的人也将能够读取用户的 Bearer 令牌(来自 LocalStorage),并可能导致问题。
最后:如果你走 LocalStorage 路线,并将 Bearer 令牌存储在 LocalStorage 中,那么你可以做的来验证你对后端的 Angular API 请求是:
- 从 LocalStorage 中获取不记名令牌。
- 向后端发出 API 请求,将 Bearer 令牌放入 HTTP
Authorization
header.
- 在您的后端,解析出 HTTP
Authorization
header,并获取令牌。
- 验证令牌以确保 JWT 有效/未过期/等等
- 就是这样!
用于验证 API 请求的标准 HTTP header 是 HTTP 授权,因此如果您想执行您描述的流程(使用 LocalStorage),只需将您的令牌放入 HTTP 授权你会很高兴去。大多数 Web 框架会自动处理此 header 的解析,并会在那里查找凭证,例如您要发送的令牌。
您可以使用此代码...
var loginApp = angular.module("LoginApp", ["LocalStorageModule"]);
loginApp.service("loginService", function ($http, $q) {
this.loginService = function (url, method, data, headers) {
var deferred = $q.defer();
$http({
method: method,
headers: headers,
data: data,
url: url
})
.success(function (response) {
deferred.resolve(response);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
};});
loginApp.controller("LoginController", [
"$http", "loginService", "localStorageService",
function (http, service, localStorageService) {
var self = this;
localStorageService.remove("authorizationData");
self.login = function () {
var url = "http://localhost:port/token";
var data = "grant_type=password&username=" + self.username + "&password=" + self.password;
service.loginService(url, "POST", data, { 'Content-Type': "application/x-www-form-urlencoded" })
.then(function (response) {
var obj = {
token: response.access_token,
userName: response.userName
};
localStorageService.set("authorizationData", obj);
}, function (error) {
alert("username or password incorrect");
});
};
}]);
出于各种原因,我需要使用服务器技术,在本例中 ASP.Net 来呈现我的 Angular JS 应用程序。因此,当用户请求索引页面时,请求将通过 ASP.Net 管道,该管道将为应用程序提供脚本、视图等服务。
我需要在应用程序中获取不记名令牌,以便它可以调用各种 Web API 服务。
从安全角度来看,在响应 header 中将不记名令牌传递给用户浏览器是否可以接受?然后当 Angular JS 应用程序启动时,它将从 header 中读取值并将其放入本地存储以供后续 API 请求使用。
用户流...
- 用户转到 members.domain.com,其中 he/she 未通过身份验证。
- 用户重定向到 OAuth 提供商。
- 用户通过提供商进行身份验证。
- 然后用户被重定向回 members.domain.com。用户现已通过身份验证并且他们有一个 cookie。
- 初始应用程序页面通过 MVC 管道呈现。根据用户声明(例如 role="recruiter" 等)检查声明并使用菜单选项(等)呈现 UI。
这会获取在用户浏览器上呈现的初始应用程序,并根据用户声明创建菜单选项。
现在缺少的部分是将不记名令牌放入浏览器,可用于调用各种 APIs。
更新:我正在根据您更新的问题完全更改我的答案。
你想做的事对我来说实际上听起来不错。听起来您要在 client-side.
上检查 JWT 作为您的 Bearer 令牌为此,您需要执行以下两项操作之一:
如果您希望通过使用 cookie 使您的应用程序更 'secure',您可以在后端创建一个路由(
/me
或类似的东西),当请求,returns 所有当前登录用户的个人数据(他们的声明,以及呈现您的 UI 所需的任何内容)。当 Angular 应用程序启动时,它可以向该页面发出请求,将通过已设置的 cookie 进行身份验证,并且只 return 前端需要的任何数据进行渲染。如果您想在纯 JS 中做所有事情,冒着更容易受到 XSS 攻击的风险,那么与其将用户的 Bearer 令牌存储在 cookie 中,不如将其存储在 HTML5本地存储。这样,您的 Angular 应用程序可以直接在浏览器中通过 Javascript 访问令牌以呈现页面。这可能会提供更快的性能,但这意味着任何可以在您的域上 运行 恶意 JS 的人也将能够读取用户的 Bearer 令牌(来自 LocalStorage),并可能导致问题。
最后:如果你走 LocalStorage 路线,并将 Bearer 令牌存储在 LocalStorage 中,那么你可以做的来验证你对后端的 Angular API 请求是:
- 从 LocalStorage 中获取不记名令牌。
- 向后端发出 API 请求,将 Bearer 令牌放入 HTTP
Authorization
header. - 在您的后端,解析出 HTTP
Authorization
header,并获取令牌。 - 验证令牌以确保 JWT 有效/未过期/等等
- 就是这样!
用于验证 API 请求的标准 HTTP header 是 HTTP 授权,因此如果您想执行您描述的流程(使用 LocalStorage),只需将您的令牌放入 HTTP 授权你会很高兴去。大多数 Web 框架会自动处理此 header 的解析,并会在那里查找凭证,例如您要发送的令牌。
您可以使用此代码...
var loginApp = angular.module("LoginApp", ["LocalStorageModule"]);
loginApp.service("loginService", function ($http, $q) {
this.loginService = function (url, method, data, headers) {
var deferred = $q.defer();
$http({
method: method,
headers: headers,
data: data,
url: url
})
.success(function (response) {
deferred.resolve(response);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
};});
loginApp.controller("LoginController", [
"$http", "loginService", "localStorageService",
function (http, service, localStorageService) {
var self = this;
localStorageService.remove("authorizationData");
self.login = function () {
var url = "http://localhost:port/token";
var data = "grant_type=password&username=" + self.username + "&password=" + self.password;
service.loginService(url, "POST", data, { 'Content-Type': "application/x-www-form-urlencoded" })
.then(function (response) {
var obj = {
token: response.access_token,
userName: response.userName
};
localStorageService.set("authorizationData", obj);
}, function (error) {
alert("username or password incorrect");
});
};
}]);