在上一篇”使用OAuth打造webapi认证服务供本身的客户端使用“的文章中咱们实现了一个采用了OAuth流程3-密码模式(resource owner password credentials)的WebApi服务端。今天咱们来实现一个js+html版本的客户端。html
1、angular客户端git
angular版本的客户端代码来自于http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/,接下来咱们作个简单的梳理,方便你们在项目中使用。web
一、新建一个angular module,咱们使用ngRoute来实现一个单页面程序,LocalStorageModule用来在本地存放token信息,angular-loading-bar是一个页面加载用的进度条。ajax
var app = angular.module('AngularAuthApp', ['ngRoute', 'LocalStorageModule', 'angular-loading-bar']);
二、新建一个constant,angular中的constant能够注入到任意service和factory中,是存储全局变量的好帮手。json
app.constant('ngAuthSettings', { apiServiceBaseUri: 'http://localhost:56646/', clientId: 'ngAuthApp' });
地址:http://localhost:56646/就是咱们本身的webApi地址。api
三、authService中定义了登陆和登出逻辑,登陆逻辑就是咱们使用OAuth2.0中的流程3获取token的过程,一旦得到到token也就意味着咱们登陆成功了。promise
var _login = function (loginData) { var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password; var deferred = $q.defer(); $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) { if (loginData.useRefreshTokens) { localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: response.refresh_token, useRefreshTokens: true }); } else { localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: "", useRefreshTokens: false }); } _authentication.isAuth = true; _authentication.userName = loginData.userName; _authentication.useRefreshTokens = loginData.useRefreshTokens; deferred.resolve(response); }).error(function (err, status) { _logOut(); deferred.reject(err); }); return deferred.promise; };
咱们按照OAuth2.0中的流程3来Post数据,拿到token信息后保存在localStorageService。cookie
三、启动AngularClient.Web项目尝试一下登陆app
因为同源策略的缘由,咱们须要在WebApi服务端启用cors,打开Startup类配置cors:cors
四、一旦登陆成功意味着咱们拿到了token,因此能够凭token访问受限的资源,例如http://localhost:56646/api/orders。只须要在每一个请求头中加入Authorization:Bearer {{token}}便可。
咱们能够使用angular的拦截功能,只须要在$http服务中拦截每一个请求,在请求头中加入token便可。
app.config(function ($httpProvider) { $httpProvider.interceptors.push('authInterceptorService'); });
angular中的provider是能够配置的,正如上面的代码咱们添加了一个authInterceptorService拦截服务。
拦截逻辑也很简单:若是在localStorageService中读到token,就添加一个header。
var _request = function (config) { config.headers = config.headers || {}; var authData = localStorageService.get('authorizationData'); if (authData) { config.headers.Authorization = 'Bearer ' + authData.token; } return config; }
五、再次登陆,当登陆成功后成功调用到了http://localhost:56646/api/orders服务
2、JQuery客户端
JQuery客户端的实现思路也差很少,首先发一个post请求获取token:
var apiServiceBaseUri = 'http://localhost:56646/'; $('#login').click(function () { var data = { 'grant_type': 'password', 'username': $('#userName').val(), 'password': $('#password').val() }; $.ajax({ url: apiServiceBaseUri + 'token', type: "POST", data: data, dataType: 'json', success: function (data) { $.cookie("token", data.access_token); getOrders(); }, error: function (xmlHttpRequest) { $("#message").html(xmlHttpRequest.responseJSON.error_description); $("#message").show(); } });
token一旦获取成功就保存在cookie中。接下来拿token去访问受限的服务:
var getOrders = function () { $.ajax({ beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + $.cookie("token")); }, url: apiServiceBaseUri + 'api/orders', type: "GET", dataType: 'json', success: function (data) { showOrderTable(data); } }); }
经过xhr.setRequestHeader('Authorization', 'Bearer ' + $.cookie("token")); 的方式将token添加到请求头,相对angular的拦截方案,此方案就显得比较繁琐了,每一个http请求都得有添加此行代码。
全部代码同步更新在 https://git.oschina.net/richieyangs/OAuthPractice.git