AngularJS客户端路由和令牌认证与web api
Posted
技术标签:
【中文标题】AngularJS客户端路由和令牌认证与web api【英文标题】:AngularJS clientside routing and token authentication with webapi 【发布时间】:2014-02-10 20:59:03 【问题描述】:我想在 SPA angularjs 应用程序中创建一个身份验证和授权示例,使用 asp.net mvc webapi 作为后端和客户端路由(无 cshtml)。以下只是可用于设置完整示例的函数示例。但我就是不能把它们放在一起。任何帮助表示赞赏。
问题:
-
什么是最佳实践:基于 Cookie 还是基于令牌?
如何以角度创建不记名令牌以对每个请求进行授权?
验证 API 函数?
如何在客户端保留登录用户的身份验证?
示例代码:
登录表格
<form name="form" novalidate>
<input type="text" ng-model="user.userName" />
<input type="password" ng-model="user.password" />
<input type="submit" value="Sign In" data-ng-click="signin(user)">
</form>
身份验证角度控制器
$scope.signin = function (user)
$http.post(uri + 'account/signin', user)
.success(function (data, status, headers, config)
user.authenticated = true;
$rootScope.user = user;
$location.path('/');
)
.error(function (data, status, headers, config)
alert(JSON.stringify(data));
user.authenticated = false;
$rootScope.user = ;
);
;
我的 API 后端 API 代码。
[HttpPost]
public HttpResponseMessage SignIn(UserDataModel user)
//FormsAuthetication is just an example. Can I use OWIN Context to create a session and cookies or should I just use tokens for authentication on each request? How do I preserve the autentication signed in user on the client?
if (this.ModelState.IsValid)
if (true) //perform authentication against db etc.
var response = this.Request.CreateResponse(HttpStatusCode.Created, true);
FormsAuthentication.SetAuthCookie(user.UserName, false);
return response;
return this.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Invalid username or password");
return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState);
授权 使用 JWT 库来限制内容。
config.MessageHandlers.Add(new JsonWebTokenValidationHandler
Audience = "123",
SymmetricKey = "456"
);
我的 API 方法
[Authorize]
public IEnumerable<string> Get()
return new string[] "value1", "value2" ;
【问题讨论】:
【参考方案1】:是否使用 cookie 身份验证或(不记名)令牌仍取决于您拥有的应用类型。据我所知,还没有任何最佳实践。但由于您正在开发 SPA,并且已经在使用 JWT 库,因此我更倾向于基于令牌的方法。
很遗憾,我无法在 ASP.NET 方面为您提供帮助,但 JWT 库通常会为您生成并验证令牌。您所要做的就是在凭证(和秘密)上调用generate
或encode
,在随每个请求发送的令牌上调用verify
或decode
。而且你不需要在服务器上存储任何状态,也不需要发送 cookie,你可能对FormsAuthentication.SetAuthCookie(user.UserName, false)
做了什么。
我确信您的库提供了有关如何使用生成/编码和验证/解码令牌的示例。
所以生成和验证不是你在客户端做的事情。
流程是这样的:
-
客户端将用户提供的登录凭据发送到服务器。
服务器验证凭据并使用生成的令牌进行响应。
客户端将令牌存储在某处(本地存储、cookie 或仅在内存中)。
客户端在每次向服务器请求时将令牌作为授权标头发送。
服务器验证令牌并相应地发送请求的资源或 401(或类似的东西)。
第 1 步和第 3 步:
app.controller('UserController', function ($http, $window, $location)
$scope.signin = function(user)
$http.post(uri + 'account/signin', user)
.success(function (data)
// Stores the token until the user closes the browser window.
$window.sessionStorage.setItem('token', data.token);
$location.path('/');
)
.error(function ()
$window.sessionStorage.removeItem('token');
// TODO: Show something like "Username or password invalid."
);
;
);
sessionStorage
只要用户打开页面,就会保留数据。如果您想自己处理过期时间,可以改用localStorage
。界面是一样的。
第 4 步:
要在每个请求中向服务器发送令牌,您可以使用 Angular 所称的 Interceptor。您所要做的就是获取先前存储的令牌(如果有)并将其作为标头附加到所有传出请求:
app.factory('AuthInterceptor', function ($window, $q)
return
request: function(config)
config.headers = config.headers || ;
if ($window.sessionStorage.getItem('token'))
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.getItem('token');
return config || $q.when(config);
,
response: function(response)
if (response.status === 401)
// TODO: Redirect user to login page.
return response || $q.when(response);
;
);
// Register the previously created AuthInterceptor.
app.config(function ($httpProvider)
$httpProvider.interceptors.push('AuthInterceptor');
);
并确保始终使用 SSL!
【讨论】:
这真是一个很好的解释,正是我想要的。非常感谢您的回答和详细的示例。 当然,很高兴我能帮上忙 :) 是否有通过隐藏的 i-frame 刷新访问令牌(假设身份验证服务器记住他们之前的权限)? 更具体地说,您为什么使用return config || $q.when(config);
而不仅仅是return config
?
使用会话存储/本地存储来存储令牌是否安全?另一个页面中的脚本可以访问令牌吗?以上是关于AngularJS客户端路由和令牌认证与web api的主要内容,如果未能解决你的问题,请参考以下文章
使用 angularjs ui 时节点/Angularjs 应用程序未接收 JSON Web 令牌