文章系列: 第一部分第二部分第三部分(本文) 介绍 早在8月份我就写了本系列的第一部分和第二部分,从那以后我就一直打算写第三部分,但是一直被这个和那个弄得跑题了(松鼠!) 在第三部分中我们要做的事情 用ASP构建RESTful API的基础。Net Web API,带有身份验证,角色等,然后创建一个新的Angular应用,它连接到这个API 源代码 本文附带的源代码可以在这里找到。 基于rest的API 好的,让我们开始我们的RESTful API。在Visual Studio中选择New Project…=比;Web =比;ASP。Net Web Application(命名为Awesome Angular Web App 2.0) =>Web API。在个人用户帐户上保留身份验证并单击OK。 现在我想要你安装三个应用程序,如果你还没有: 邮差node . js提琴手 一旦你安装了邮差,浏览到以下网址在Chrome: chrome扩展:/ / fdmmgilgnpjigdojojpjoooidkmcomcm / index . html 如果你熟悉ASP。净MVC Web API在某些方面会有一个相对较小的学习曲线,因为它是基于相同的技术,也是基于MVC的等,但在其他方面更大的学习曲线(从的角度需要了解HTTP RESTful API是什么和如何架构师等。这不是那篇文章,但我建议你读一本这方面的好书。) 按F5(或任何调试键)启动我们的Web API项目。你应该看到这样的东西: 点击API。当我们构建一个API时,这个页面会自动更新有关所有端点的信息以及相关的HTTP请求类型。点击这里的一个方法会给你关于那个特定端点的详细信息,包括参数等等。在某种程度上,它本质上是自我记录的。 网站还在运行,邮递员跑吧。我们将创建一个用户和登录。Web API使用基于令牌的身份验证,而不是基于cookie的身份验证。其工作方式非常简单,如果您使用有效的用户名和密码登录,API将返回一个令牌,以及关于该令牌有效持续时间的信息。您将此令牌作为头添加到以下所有HTTP请求中,然后服务器就知道您是谁。 就像普通的ASP。Net身份验证,您可以使用[Authenticate]属性限制对控制器或方法的访问。您还可以创建角色,并允许不同的用户根据他们的角色访问API的不同部分。 让我们创建一个用户。查看URL以确定您的API正在运行的端口(它运行localhost,冒号,端口号),然后将以下内容放入邮差的URL栏,用您的端口替换8888: http://localhost:8888/api/Account/register 在下面的栏中,点击raw并粘贴以下JSON到下面的文本框(不要担心,AngularJS的东西来了,但我们需要先完成这个): 隐藏,复制Code
{ "Email": "email@email.com", "Password": "Password1!", "ConfirmPassword": "Password1!" }
我们还需要将此请求的内容类型设置为json,因此单击header并添加名为content - type的新头部,其值为application/json。最后,在下拉列表中将请求类型更改为POST。 邮递员的长相应该是这样的: 点击发送。这将花费几秒钟的时间,因为ASP。Net正在后台创建数据库,但一旦它完成了,你应该得到一个200 OK的响应,像这样: 如果你查看fiddler,你应该也能找到这个请求。在这里查看不同的标签/按钮,探索请求的细节: 现在我们已经创建了一个用户,让我们继续登录。更改URL为: http://localhost:8888/token 这仍然是一篇文章,但是现在我们想将数据模式更改为x-www-form- urlencodes,所以单击这个按钮。添加以下字段: grant_type: password username: email@email.com(或您注册的其他地址)password: Password1!(或者你注册时设置的密码) 邮递员现在应该是这个样子: 点击发送,类似于以下内容将返回: 隐藏,复制Code
{ "access_token": "R-AejC88wImTKUulwlZBRsR620zXuHcrjV26UGObVjl5s9aqJIhs2hzt60CdLhL0hXNR-kyLTgrTfiMDV4JZJsmC1jV3MQHKcScsW6lYAMz1kegSyQiSfRHVj8W1E76x9uiHYJVIWhwA_RH7GkTn3K_Z0ugV_0qsSd1cWZ5qpqRedrS1vbHNIr7PR-FvAcKGA5c0S7ffadD8TP6N8OX8AyEg2t5rxppAeT2AlqlY3G5HdJqDkPgXQx5pL_xXRWkQCuOhIgUCm-6TDAksNf-EJ7HzPKD7nl7KU8Pd66rQO56p_vtq6eOO9OtgAmN8FviR-gNKGHCsz4udPrAKTExF_Ht4hBpbLoiGIXIbVUpzTeB-RMZUMMcRgByo4tCELjd41pV0mjaXHS6s7mTuwlgGmxiAU5AoYgNTXVOe9YegZMvjW_lAIUw0YlZ0m7RAiPOTTDlRzmV1ntm3YGvAN9h9_m027twqfGz5YsHsbh3RYW8", "token_type": "bearer", "expires_in": 1209599, "userName": "email@email.com", ".issued": "Sun, 16 Nov 2014 22:55:45 GMT", ".expires": "Sun, 30 Nov 2014 22:55:45 GMT" }
RESTful API和Web API,非常有限的入门 当我们创建Web API项目时,它为我们创建了一个名为ValuesController的控制器,其中包含五个方法: Get(重载带有参数的版本)发布put delete 控制器的名称对应于URL(如在ASP中)。方法的名称对应于请求的HTTP谓词。因此,如果您想为HTTP Get请求编写端点,您可以创建一个名为Get的方法。 如何构建一个RESTful API超出了本文的范围,但通常您使用以下方法: Get request to Get something post to do something(执行一个动作)put to put something somewhere(如在数据库中)delete to delete 你总是响应HTTP请求与状态码指示的结果。当我们注册和登录时,我们得到一个2每次00响应。您可以在Postman中随意处理这些请求(所有的东西都保存在历史中),提供不同的值,删除/添加值等等,在不同的场景中看到不同的状态代码返回。例如,如果您在登录时提供了错误的密码,您会得到400个错误请求的响应。 维基百科的页面很好地分解了各种状态码。一旦你读了这篇文章,我建议你到这里来阅读关于7xx系列的文章。你将在维基百科文章之后需要它。 所有的HTTP请求都可以包含header,而不管它们的HTTP动词(Get, Post等)是什么,有些还可以包含body,而有些则不能。例如,Post可以包含body,但是Get不能。在Web API中,这个主体是使用stronly类型的c#对象构建的,并从方法返回。 让我们尝试调用这个values控制器的Get方法。在邮差,改变HTTP动作类型,以获取在下拉列表和URL如下: http://localhost:8888/api/values 现在将内容类型保留为application/json。邮递员应该是这样的: 点击发送,我们会收到401未经授权的回复。这是因为Values控制器是由[Authorize]属性保护的!哎! 在Postman中,添加一个名为Authorization的新标题,其值为holder,后面是空格,后面是我们之前取回的令牌。邮递员现在应该是这样的: 再次点击发送,成功!我们从API得到以下JSON: 隐藏,复制Code
[ "value1", "value2" ]
玩弄Postman调用values控制器中的每个方法,并改变方法以返回不同类型的对象。您将能够看到所有这些行动在邮差也,以及每个请求的详细信息。很酷,不是吗? 这应该是一篇关于角绳的文章,但我们还没有做任何角绳!去找角兔吧! 好吧,好吧。这一次,我们不打算创建一个ASP。Net MVC应用程序来容纳我们的网站,我们将创建一切使用纯旧的CSS, HTML和Javascript和一点Node.JS。 我之前要求您安装Node.JS。因为当前版本的Node有错误。JS,你还需要在以下位置创建一个名为npm的目录: C:Users{{您的用户名}} AppData 漫游 这个问题可能会在您阅读本文时得到解决,如果是这样的话,请忽略(也许可以留下评论)。 为你的网站创建一个目录,用你最喜欢的文本编辑器(我用的是Atom)创建一个index.html文件,包含以下内容: 隐藏,复制Code
<!DOCTYPE html> <html> <head> <title>Awesome Angular Web App 2.0</title> </head> <body> Hello Again! </body> </html>
现在打开Node.js命令提示符,运行以下命令: 安装http-server -g 这将安装一个内置在Javascript中的轻量级web服务器,叫做http-server,我们可以在它上面运行Angular应用。g旗代表全球。这意味着服务器被安装到你的PC上,并且可以在任何地方运行。如果忽略了这个,服务器将被安装到您当前所在的目录中。 现在导航到存放网站的目录,并运行http-server。你的窗口应该是这样的: 在浏览器中,浏览到http://localhost:8080/。 这不是很棒吗? 添加一个子目录Scripts和一个子目录Styles。我们已经在第一部分和第二部分讨论过了这些内容,所以我不打算在这里解释太多,只是复制粘贴我创建的每个文件的内容: index . html 隐藏,复制Code
<!DOCTYPE html> <html> <head> <title>Awesome Angular Web App 2.0</title> </head> <body ng-app="AwesomeAngularWebApp" ng-controller="BaseController"> {{helloAgain}} <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script> <script src="/Scripts/Controllers/BaseController.js"></script> <script src="/Scripts/AwesomeAngularWebApp.js"></script> </body> </html>
脚本/ AwesomeAngularWebApp.js 隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', []); AwesomeAngularWebApp.controller('BaseController', BaseController);
脚本/控制器/ BaseController.js 隐藏,复制Code
var BaseController = function($scope){ $scope.helloAgain = 'Hello Angular 1.3!'; } BaseController.$inject = ['$scope'];
http://localhost:8080/现在应该如下所示: 当身份验证令牌从API返回时,我们需要一个存储它的地方。我们可以在服务中这样做。AngularJS中的服务是单例的,在应用程序启动时创建一个实例,你可以通过依赖注入来传递这个实例。它们是存储应用程序的多个部分所需的值的好地方。 脚本/服务/ SessionService.js 隐藏,复制Code
var AuthenticationService = function(){ this.token = undefined; }
脚本/ AwesomeAngularWebApp.js 隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', []); AwesomeAngularWebApp.controller('BaseController', BaseController); AwesomeAngularWebApp.service('SessionService', SessionService);
让我们创建工厂来登录和注册: 脚本/工厂/ LoginFactory.js 隐藏,收缩,复制Code
var LoginFactory = function($http, $q, SessionService){ return function(username, password){ var result = $q.defer(); var params = {grant_type: "password", userName: username, password: password}; $http({ method: 'POST', url: SessionService.apiUrl + '/token', transformRequest: function(obj) { var str = []; for(var p in obj) str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); return str.join("&"); }, data: params, headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'} }) .success(function(response){ result.resolve(response); }) .error(function(response){ result.reject(response); }); return result.promise; } } LoginFactory.$inject = ['$http', '$q', 'SessionService'];
脚本/工厂/ RegisterFactory.js 隐藏,复制Code
var RegisterFactory = function($http, $q, SessionService){ return function(email, password, confirmPassword){ var result = $q.defer(); $http({ method: 'POST', url: SessionService.apiUrl + '/api/Account/register', data: {Email: email, Password: password, ConfirmPassword: confirmPassword}, headers: {'Content-Type': 'application/json'} }) .success(function(response){ result.resolve(response); }) .error(function(response){ result.reject(response); }); return result.promise; } } RegisterFactory.$inject = ['$http', '$q', 'SessionService'];
脚本/ AwesomeAngularWebApp.js 隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', []); AwesomeAngularWebApp.controller('BaseController', BaseController); AwesomeAngularWebApp.service('SessionService', SessionService); AwesomeAngularWebApp.factory('LoginFactory', LoginFactory); AwesomeAngularWebApp.factory('RegisterFactory', RegisterFactory);
现在我要为登录和注册视图创建一个控制器(我们马上就会做): 脚本/控制器/ LoginController.js 隐藏,复制Code
var LoginController = function($scope, $location, LoginFactory, SessionService){ $scope.loginForm = { username: undefined, password: undefined, errorMessage: undefined }; $scope.login = function(){ LoginFactory($scope.loginForm.username, $scope.loginForm.password) .then(function(response){ SessionService.token = response.access_token; $location.path('/'); }, function(response){ $scope.loginForm.errorMessage = response.error_description; }); } } LoginController.$inject = ['$scope', '$location', 'LoginFactory', 'SessionService'];
脚本/控制器/ RegisterController.js 隐藏,复制Code
var RegisterController = function($scope, LoginFactory, RegisterFactory, SessionService){ $scope.registerForm = { username: undefined, password: undefined, confirmPassword: undefined, errorMessage: undefined }; $scope.register = function(){ RegisterFactory($scope.registerForm.username, $scope.registerForm.password, $scope.registerForm.confirmPassword) .then(function(){ LoginFactory($scope.registerForm.username, $scope.registerForm.password) .then(function(response){ SessionService.token = response.access_token; }, function(response){ $scope.registerForm.errorMessage = response; }); }, function(response){ $scope.registerForm.errorMessage = response; }); } } RegisterController.$inject = ['$scope', 'LoginFactory', 'RegisterFactory', 'SessionService'];
脚本/ AwesomeAngularWebApp.js 隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', []); AwesomeAngularWebApp.controller('BaseController', BaseController); AwesomeAngularWebApp.controller('LoginController', LoginController); AwesomeAngularWebApp.controller('RegisterController', RegisterController); AwesomeAngularWebApp.service('SessionService', SessionService); AwesomeAngularWebApp.factory('LoginFactory', LoginFactory); AwesomeAngularWebApp.factory('RegisterFactory', RegisterFactory);
这些控制器的视图,带有更新的路由代码: 视图/ Login.html 隐藏,复制Code
<form role="form" ng-submit="login()"> <div class="form-group"> <label for="emailAddress">Email address</label> <input type="email" class="form-control" id="emailAddress" placeholder="Enter email" ng-model="loginForm.username"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" placeholder="Password" ng-model="loginForm.password"> </div> <p class="help-block" ng-if="loginForm.errorMessage">{{loginForm.errorMessage}}</p> </div> <button type="submit" class="btn btn-default">Login</button> </form>
视图/ Register.html 隐藏,复制Code
<form role="form" ng-submit="register()"> <div class="form-group"> <label for="emailAddress">Email address</label> <input type="email" class="form-control" id="emailAddress" placeholder="Enter email" ng-model="registerForm.username"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" placeholder="Password" ng-model="registerForm.password"> </div> <div class="form-group"> <label for="password">Confirm Password</label> <input type="password" class="form-control" id="password" placeholder="Confirm Password" ng-model="registerForm.confirmPassword"> </div> <p class="help-block" ng-if="registerForm.errorMessage">{{registerForm.errorMessage}}</p> </div> <button type="submit" class="btn btn-default">Register</button> </form>
脚本/ AwesomeAngularWebApp.js隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', ['ngRoute']); AwesomeAngularWebApp.controller('BaseController', BaseController); AwesomeAngularWebApp.controller('LoginController', LoginController); AwesomeAngularWebApp.controller('RegisterController', RegisterController); AwesomeAngularWebApp.service('SessionService', SessionService); AwesomeAngularWebApp.factory('LoginFactory', LoginFactory); AwesomeAngularWebApp.factory('RegisterFactory', RegisterFactory); var ConfigFunction = function($routeProvider) { $routeProvider .when('/login', { templateUrl: 'views/login.html', controller: 'LoginController' }) .when('/register', { templateUrl: 'views/register.html', controller: 'RegisterController' }); }; ConfigFunction.$inject = ['$routeProvider']; AwesomeAngularWebApp.config(ConfigFunction);
index . html 隐藏,收缩,复制Code
<!DOCTYPE html> <html> <head> <title>Awesome Angular Web App 2.0</title> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.min.css"> </head> <body ng-app="AwesomeAngularWebApp" ng-controller="BaseController"> {{helloAgain}} <a href="/#/login" ng-if="!loggedIn()">Login</a> <a href="/#/register" ng-if="!loggedIn()">Register</a> <span class="label label-success" ng-if="loggedIn()">Logged In</span> <div ng-view></div> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular-route.min.js"></script> <script src="/Scripts/Controllers/BaseController.js"></script> <script src="/Scripts/Controllers/LoginController.js"></script> <script src="/Scripts/Controllers/RegisterController.js"></script> <script src="/Scripts/Services/SessionService.js"></script> <script src="/Scripts/Factories/LoginFactory.js"></script> <script src="/Scripts/Factories/RegisterFactory.js"></script> <script src="/Scripts/AwesomeAngularWebApp.js"></script> </body> </html>
脚本/ BaseController.js 隐藏,复制Code
var BaseController = function($scope, SessionService){ $scope.helloAgain = 'Hello Angular 1.3!'; $scope.loggedIn = function(){ return SessionService.token !== undefined; } } BaseController.$inject = ['$scope', 'SessionService'];
好,让我们导航回http://localhost:8080/,确保所有东西都连接好了。您应该能够浏览到登录和注册视图。检查你的浏览器控制台,如果有错误,你可能漏掉了一个步骤(或者我搞砸了,如果是这样,请在评论中告诉我) 让我们尝试登录 为了让你不用向上滚动,下面是我们之前创建的用户的用户名和密码(除非你修改了它们,否则向上滚动是没有用的): 用户名:email@email.com密码:Password1! 让我们浏览到登录表单,并尝试登录。哦不: 我们的API在一个服务器上,而我们的网站在另一个服务器上,所以登录请求被浏览器出于安全原因阻止。我们可以用CORS解决这个问题。 回到Visual Studio,从View =>打开nuget包管理器控制台其他窗口=比;包管理器控制台。运行以下命令: 隐藏,复制Code
Install-Package Microsoft.Owin.Cors
在启动。cs,修改配置,使其包含以下内容: 隐藏,复制Code
public void Configuration(IAppBuilder app) { app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); ConfigureAuth(app); }
让我们试着再次登录,首先使用一个故意不正确的用户名/密码组合: 很好,我们从服务器取回400,并在屏幕上显示错误消息。现在让我们正确登录: 史诗!我们回到主页,我们的令牌存储在服务中,登录和注册链接消失了。 现在我们将编写一个工厂来从API中的ValuesController类中获取值: 脚本/工厂/ GetValuesFactory.js 隐藏,复制Code
var GetValuesFactory = function($http, $q, SessionService){ return function(){ var result = $q.defer(); $http({ method: 'GET', url: SessionService.apiUrl + '/api/Values', headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + SessionService.token} }) .success(function(response){ result.resolve(response); }) .error(function(response){ result.reject(response); }); return result.promise; } } GetValuesFactory.$inject = ['$http', '$q', 'SessionService'];
我们马上要创建的视图控制器: 脚本/控制器/ ValuesController.js 隐藏,复制Code
var ValuesController = function($scope, GetValuesFactory, SessionService){ $scope.values = []; $scope.error = { message: undefined }; $scope.getValues = function(){ GetValuesFactory() .then(function(response){ $scope.values = response; }, function(response){ $scope.error.message = response.Message; }); } } ValuesController.$inject = ['$scope', 'GetValuesFactory', 'SessionService'];
一个视图: 视图/ values.html 隐藏,复制Code
<button ng-click="getValues()">Get Values</button> <ul class="nav nav-pills" ng-if="values.length > 0"> <li ng-repeat="value in values">{{value}}<li> </ul> <p class="help-block" ng-if="error.message">{{error.message}}</p>
更新的路径和新jazz的注册: 脚本/ AwesomeAngularWebApp.js 隐藏,收缩,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', ['ngRoute']); AwesomeAngularWebApp.controller('BaseController', BaseController); AwesomeAngularWebApp.controller('LoginController', LoginController); AwesomeAngularWebApp.controller('RegisterController', RegisterController); AwesomeAngularWebApp.controller('ValuesController', ValuesController); AwesomeAngularWebApp.service('SessionService', SessionService); AwesomeAngularWebApp.factory('LoginFactory', LoginFactory); AwesomeAngularWebApp.factory('RegisterFactory', RegisterFactory); AwesomeAngularWebApp.factory('GetValuesFactory', GetValuesFactory); var ConfigFunction = function($routeProvider) { $routeProvider .when('/login', { templateUrl: 'views/login.html', controller: 'LoginController' }) .when('/register', { templateUrl: 'views/register.html', controller: 'RegisterController' }) .when('/values', { templateUrl: 'views/values.html', controller: 'ValuesController' }); }; ConfigFunction.$inject = ['$routeProvider']; AwesomeAngularWebApp.config(ConfigFunction);
新控制器/工厂的链接和脚本标签: 隐藏,收缩,复制Code
<!DOCTYPE html> <html> <head> <title>Awesome Angular Web App 2.0</title> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.min.css"> </head> <body ng-app="AwesomeAngularWebApp" ng-controller="BaseController"> {{helloAgain}} <a href="/#/login" ng-if="!loggedIn()">Login</a> <a href="/#/register" ng-if="!loggedIn()">Register</a> <a href="/#/values">Values</a> <span class="label label-success" ng-if="loggedIn()">Logged In</span> <div ng-view></div> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular-route.min.js"></script> <script src="/Scripts/Controllers/BaseController.js"></script> <script src="/Scripts/Controllers/LoginController.js"></script> <script src="/Scripts/Controllers/RegisterController.js"></script> <script src="/Scripts/Controllers/ValuesController.js"></script> <script src="/Scripts/Services/SessionService.js"></script> <script src="/Scripts/Factories/LoginFactory.js"></script> <script src="/Scripts/Factories/RegisterFactory.js"></script> <script src="/Scripts/Factories/GetValuesFactory.js"></script> <script src="/Scripts/AwesomeAngularWebApp.js"></script> </body> </html>
好,把所有东西都点燃。首先,导航到我们的新值视图并点击按钮。Web API返回一个显示在屏幕上的401(未经授权)http错误。登录并再次按下按钮,一切工作正常。 别忘了我 目前,如果您登录,然后刷新页面,您将被踢出并需要重新进行身份验证。我们可以通过使用AngularJS的ng-cookie模块将令牌存储在cookie中来解决这个问题。更新index.html,像这样从Cloudflare下拉这个(添加到角路径标签后): 隐藏,复制Code
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular-cookies.min.js"></script>
更新AwesomeAngularWebApp.js在我们的app中注册这个模块: 隐藏,复制Code
var AwesomeAngularWebApp = angular.module('AwesomeAngularWebApp', ['ngRoute', 'ngCookies']);
更新SessionService以获取令牌并将其存储在cookie中: 隐藏,复制Code
var SessionService = function($cookies){ this.token = undefined; this.getToken = function(){ if(!$cookies.awesomeAngularWebAppToken){ if(!this.token){ return undefined; } this.setToken(this.token); } return $cookies.awesomeAngularWebAppToken; } this.setToken = function(token){ this.token = token; $cookies.awesomeAngularWebAppToken = token; } this.apiUrl = 'http://localhost:5586'; } SessionService.$inject = ['$cookies'];
LoginController和RegisterController, BaseController和GetValuesFactory调用新的getter和setter方法: 脚本/控制器/ LoginController.js 隐藏,复制Code
var LoginController = function($scope, $location, LoginFactory, SessionService){ $scope.loginForm = { username: undefined, password: undefined, errorMessage: undefined }; $scope.login = function(){ LoginFactory($scope.loginForm.username, $scope.loginForm.password) .then(function(response){ SessionService.setToken(response.access_token); $location.path('/'); }, function(response){ $scope.loginForm.errorMessage = response.error_description; }); } } LoginController.$inject = ['$scope', '$location', 'LoginFactory', 'SessionService'];
脚本/控制器/ RegisterController.js 隐藏,复制Code
var RegisterController = function($scope, LoginFactory, RegisterFactory, SessionService){ $scope.registerForm = { username: undefined, password: undefined, confirmPassword: undefined, errorMessage: undefined }; $scope.register = function(){ RegisterFactory($scope.registerForm.username, $scope.registerForm.password, $scope.registerForm.confirmPassword) .then(function(){ LoginFactory($scope.registerForm.username, $scope.registerForm.password) .then(function(response){ SessionService.setToken(response.access_token); }, function(response){ $scope.loginForm.errorMessage = response; }); }, function(response){ $scope.registerForm.errorMessage = response; }); } } RegisterController.$inject = ['$scope', 'LoginFactory', 'RegisterFactory', 'SessionService'];
脚本/控制器/ BaseController.js 隐藏,复制Code
var BaseController = function($scope, SessionService){ $scope.helloAgain = 'Hello Angular 1.3!'; $scope.loggedIn = function(){ return SessionService.getToken() !== undefined; } } BaseController.$inject = ['$scope', 'SessionService'];
脚本/工厂/ GetValuesFactory.js 隐藏,复制Code
var GetValuesFactory = function($http, $q, SessionService){ return function(){ var result = $q.defer(); $http({ method: 'GET', url: SessionService.apiUrl + '/api/Values', headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + SessionService.getToken()} }) .success(function(response){ result.resolve(response); }) .error(function(response){ result.reject(response); }); return result.promise; } } GetValuesFactory.$inject = ['$http', '$q', 'SessionService'];
现在,当您登录并点击刷新,您仍然登录!Wohoo ! 角色 如前所述,不同的用户可以具有不同的角色。我发现仅使用SQL设置角色是最简单的。我们现在开始吧。 打开SQL Server Management Studio,像这样在as (localdb)v11.0中输入服务器名,然后点击连接: 你应该会看到一个名为aspnet-Awesome Angular Web App 2.0-20141116095710的数据库,最后的数字就是这个数据库创建时的时间戳。 让我们创建一个名为SuperAdmin的角色,并分配我们创建该角色的用户。使用以下SQL语句更新AspNetRoles表: 隐藏,复制Code
INSERT INTO [aspnet-Awesome Angular Web App 2.0-20141116095710].[dbo].[AspNetRoles] VALUES('8138aad6-dfdb-422d-862d-8d5acab5c8a1', 'SuperAdmin')
现在让我们更新ValuesController,使其只允许超级管理员获取值。像这样修改控制器上的[Authorize]属性: 隐藏,复制Code
[Authorize(Roles = "SuperAdmin")]
重要提示:当我们停止和启动API时,我们的令牌将不再工作,因为它们存储在内存中,所以你将需要清除你的浏览器缓存在同一时间。 现在,当我们去我们的网站和登录(与以下凭据为懒惰): 用户名:email@email.com密码:Password1! 我们得到了401未经授权的赔偿。这是因为我们不是超级管理员组的成员。让我们解决这个问题,首先运行以下SQL对[AspNetUsers]看看我们的id是: 隐藏,复制Code
SELECT [Id] FROM [aspnet-Awesome Angular Web App 2.0-20141116095710].[dbo].[AspNetUsers] WHERE [Email] = 'email@email.com'
对我来说,id是e79c2336-265e-42d0-a62c-df44a3dfa0f4,你的会不一样,所以在下面的SQL中将这个id替换为你的。下面的SQL将用户添加到角色中: 隐藏,复制Code
INSERT INTO [aspnet-Awesome Angular Web App 2.0-20141116095710].[dbo].[AspNetUserRoles] VALUES('e79c2336-265e-42d0-a62c-df44a3dfa0f4', '8138aad6-dfdb-422d-862d-8d5acab5c8a1')
你现在是一个超级管理员,但你不是当你登录时,所以清空你的浏览器缓存,登录现在再试一次。如果一切正常,您将能够成功地完成针对Values控制器的HTTP请求,但是不属于超级管理员角色的其他用户则不能。 回顾 今天,我们用ASP创建了一个RESTful API。Net Web API,一个运行在node.js服务器上的AngularJS应用程序,并成功配置该应用程序根据API进行身份验证,将令牌存储在cookie中的a中。我们还创建了一个角色,并将API的一个区域限制为该角色的用户。 接下来是第四部分 你想看什么?留下你的评论。 安全 来自微软的Troy Hunt使用本文中的代码作为Pluralsight客户端框架安全课程的基础。我强烈建议你去看看。 评论/批评等 如果有任何评论/批评/问题,请对这篇文章发表评论,我会回复你的。感谢你的阅读 本文转载于:http://www.diyabc.com/frontweb/news1693.html