我想使用 asp.net mvc webapi 作为后端和客户端路由(无 cshtml)在 SPA angularjs 应用程序中创建一个身份验证和授权示例。以下只是可用于设置完整示例的函数示例。但我就是无法把它们放在一起。任何帮助表示赞赏。
问题:
- 最佳实践是什么:基于 Cookie 还是基于 token ?
- 如何在 Angular 中创建不记名 token 以对每个请求进行授权?
- 验证 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>
身份验证 Angular Controller
$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" }; }
最佳答案
是否使用 cookie 身份验证或(不记名) token 仍然取决于您拥有的应用程序类型。据我所知,目前还没有任何最佳实践。但由于您正在开发 SPA,并且已经在使用 JWT 库,因此我更喜欢基于 token 的方法。
不幸的是,我无法帮助您使用 ASP.NET,但通常 JWT 库会为您生成并验证 token 。您所要做的就是对凭据(和 secret )调用generate
或encode
并verify
或decode
在每个请求发送的 token 上。而且您不需要在服务器上存储任何状态,也不需要发送 cookie,这可能是您使用 FormsAuthentication.SetAuthCookie(user.UserName, false)
所做的事情。
我确信您的库提供了有关如何使用生成/编码和验证/解码 token 的示例。
因此生成和验证不是您在客户端执行的操作。
流程是这样的:
- 客户端将用户提供的登录凭据发送到服务器。
- 服务器对凭据进行身份验证并使用生成的 token 进行响应。
- 客户端将 token 存储在某处(本地存储、Cookie 或内存中)。
- 客户端在每次向服务器发出请求时都会将 token 作为授权 header 发送。
- 服务器验证 token 并采取相应措施,发送请求的资源或 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 步:
要将每个请求的 token 发送到服务器,您可以使用 Angular 所说的 Interceptor 。您所要做的就是获取之前存储的 token (如果有)并将其作为 header 附加到所有传出请求中:
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!
关于使用 Web api 的 AngularJS 客户端路由和 token 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21255203/