使用OAuth打造webapi认证服务供自己的客户端使用(二)
目录
在上一篇”使用OAuth打造webapi认证服务供自己的客户端使用“的文章中我们实现了一个采用了OAuth流程3-密码模式(resource owner password credentials)的WebApi服务端。今天我们来实现一个js+html版本的客户端。
一、angular客户端
angular版本的客户端代码来自于http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/,接下来我们做个简单的梳理,方便大家在项目中使用。
1、新建一个angular module,我们使用ngRoute来实现一个单页面程序,LocalStorageModule用来在本地存放token信息,angular-loading-bar是一个页面加载用的进度条。
1 | var app = angular.module( 'AngularAuthApp' , [ 'ngRoute' , 'LocalStorageModule' , 'angular-loading-bar' ]); |
2、新建一个constant,angular中的constant可以注入到任意service和factory中,是存储全局变量的好帮手。
1 2 3 4 | app.constant( 'ngAuthSettings' , { clientId: 'ngAuthApp' }); |
地址:http://localhost:56646/就是我们自己的webApi地址。
3、authService中定义了登录和登出逻辑,登录逻辑就是我们使用OAuth2.0中的流程3获取token的过程,一旦获得到token也就意味着我们登录成功了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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。
3、启动AngularClient.Web项目尝试一下登录
由于同源策略的原因,我们需要在WebApi服务端启用cors,打开Startup类配置cors:
4、一旦登录成功意味着我们拿到了token,所以可以凭token访问受限的资源,例如http://localhost:56646/api/orders。只需要在每个请求头中加入Authorization:Bearer {{token}}即可。
我们可以使用angular的拦截功能,只需要在$http服务中拦截每个请求,在请求头中加入token即可。
1 2 3 | app.config( function ($httpProvider) { $httpProvider.interceptors.push( 'authInterceptorService' ); }); |
angular中的provider是可以配置的,正如上面的代码我们添加了一个authInterceptorService拦截服务。
拦截逻辑也很简单:如果在localStorageService中读到token,就添加一个header。
1 2 3 4 5 6 7 8 9 10 11 | var _request = function (config) { config.headers = config.headers || {}; var authData = localStorageService.get( 'authorizationData' ); if (authData) { config.headers.Authorization = 'Bearer ' + authData.token; } return config; } |
5、再次登录,当登录成功后成功调用到了http://localhost:56646/api/orders服务
二、JQuery客户端
JQuery客户端的实现思路也差不多,首先发一个post请求获取token:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | $( '#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去访问受限的服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)