Web API使用记录系列OAuth授权与身份校验
Posted xihao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web API使用记录系列OAuth授权与身份校验相关的知识,希望对你有一定的参考价值。
呼,开干第四篇,基于OWIN搭建OAuth认证授权服务器与接口身份校验。
OAuth包含授权码模式、密码模式、客户端模式和简化模式,这里我们文章记录的是密码模式和客户端模式。
目录
引用安装
授权处理-发放Token
用户名密码授权
客户端授权
身份校验-校验失败自定义返回信息
TestClient增加token获取
一、引用安装
除了Owin使用时安装的引用外,还需要安装以下引用
Microsoft.Owin.Security.OAuth
Microsoft.Owin.Security.Cookies
Microsoft.AspNet.Identity.Owin
二、搭建授权认证
修改StartUp,添加关键词partial
在App_Start下新建StartUp.Auth,同样使用关键词partial,添加ConfiguerAuth,代码如下:
1 public partial class StartUp 2 { 3 /// <summary> 4 /// OAuth配置 5 /// </summary> 6 /// <param name="app"></param> 7 public void ConfigureAuth(IAppBuilder app) 8 { 9 app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions 10 { 11 AllowInsecureHttp = true, 12 TokenEndpointPath = new PathString("/api/token"),//授权地址 13 AccessTokenExpireTimeSpan = TimeSpan.FromHours(24), //过期时间 14 AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, 15 Provider = new SampleAuthorizationServerProvider() //授权服务 16 }); 17 } 18 }
SampleAuthorizationServerProvider是提供授权服务的方法,继承自OAuthAuthorizationServerProvider,包含客户端认证和用户名密码认证,代码如下
1 /// <summary> 2 /// 授权服务 3 /// </summary> 4 public class SampleAuthorizationServerProvider : OAuthAuthorizationServerProvider 5 { 6 #region 客户端授权 7 /// <summary> 8 /// 客户端验证 9 /// </summary> 10 /// <param name="context"></param> 11 /// <returns></returns> 12 public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 13 { 14 string clientId = ""; 15 string clientSecret = ""; 16 //获取传入的客户端id和客户端校验码 17 context.TryGetFormCredentials(out clientId, out clientSecret); 18 if (clientId == "发放的客户端id" && clientSecret == "发放的客户端校验码") 19 { 20 context.Validated(clientId); 21 } 22 else 23 { 24 context.SetError("invalid_client", "client is not valid"); 25 } 26 return base.ValidateClientAuthentication(context); 27 } 28 29 /// <summary> 30 /// 客户端授权-生成access token 31 /// </summary> 32 /// <param name="context"></param> 33 /// <returns></returns> 34 public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context) 35 { 36 var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType); 37 oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, "app"));//可以继续加一些其它信息 38 var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties() { AllowRefresh = false }); 39 context.Validated(ticket); 40 return base.GrantClientCredentials(context); 41 } 42 #endregion 43 44 #region 用户名密码授权 45 public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 46 { 47 if (context.UserName == "用户名" && context.Password == "用户密码") 48 { 49 var props = new AuthenticationProperties(new Dictionary<string, string> 50 { 51 { 52 "userName", context.UserName 53 } 54 }); 55 var identity = new ClaimsIdentity("userinfo"); 56 identity.AddClaim(new Claim("DisplayName", "张三")); 57 identity.AddClaim(new Claim("DutyName", "总监")); 58 59 var ticket = new AuthenticationTicket(identity, props); 60 61 context.Validated(ticket); 62 } 63 else 64 { 65 context.SetError("invalid_user", "username or password error"); 66 } 67 return base.GrantResourceOwnerCredentials(context); 68 } 69 #endregion 70 71 }
在根目录App_Start中增加 ConfigureAuth(app);
请求Token(以客户端验证为示例)
1 $.ajax({ 2 url: ‘/api/token‘, 3 type: ‘post‘, 4 data: { 5 "grant_type": "client_credentials", 6 "client_id": $("#clientid").val(), 7 "client_secret": $("#clientscuret").val() 8 }, 9 dataType: "json", 10 success: function (data) { 11 var accessToken = data.access_token; 12 console.log("获取到的token:"+accessToken); 13 } 14 });
三、身份认证与身份认证失败自定义返回
增加身份认证,只需要在需要使用的controller上增加 特性 [Authorize]
不需要启用验证的使用特性 [AllowAnonymous]
认证失败返回401,但为了和我们项目的返回数据结构一致,我们需要在认证失败的时候修改返回,新建过滤器继承AuthorizeAttribute,完事将使用Authorized的地方替换为自定义的过滤器
1 public class CustomAuthorizeAttribute:AuthorizeAttribute 2 { 3 protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) 4 { 5 base.HandleUnauthorizedRequest(actionContext); 6 actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK) 7 { 8 Content = new StringContent("项目返回的数据格式数据") 9 }; 10 } 11 }
四、TestClient
为了方便在线测试接口添加token的方便,我们需要给弹出的调用窗口增加authorization的header信息、获取token的操作;并将获取到的token存储到cookie,打开窗口时存在自填充,省去每次的获取操作
》文件TestClientDialogs文件,在<div class="panel"> 内添加如下代码
1 <div style="margin-bottom:10px;background:#EFEFEF;border:1px solid #ccc;padding:10px"> 2 <div> 3 客户端id: 4 <input type="text" id="clientid" value="admin" /> 5 客户端securet: 6 <input type="password" id="clinetsecuret" value="admin" /> 7 <a href=‘javascript:;‘ id="btngettk">获取 Token</a> 8 </div> 9 <div style="padding:5px;background:#ffd800;" id="getmsg"> <span> 正在获取Token,请稍后...</span></div> 10 </div> 11 12 <hr />
》WebApiTestClient.js中修改如下(TestClientViewModel方法末尾添加):
1 //支持弹出窗口自动填充token 2 var accessToken; 3 try { 4 accessToken = $.cookie("token"); 5 } catch (e) { 6 console.log(e); 7 } 8 addOrReplaceHeader(self.RequestHeaders, "authorization", "Bearer " + accessToken); 9 //不存在token时点击获取按钮获取token 10 $("#getmsg").hide(); 11 $("#btngettk").click(function () { 12 $("#getmsg").show(); 13 $.ajax({ 14 url: ‘/api/token‘, 15 type: ‘post‘, 16 data: { 17 "grant_type": "client_credentials", 18 "client_id": $("#txtusername").val(), 19 "client_secret": $("#txtpwd").val() 20 }, 21 dataType: "json", 22 success: function (data) { 23 var headers = self.RequestHeaders; 24 var accessToken = data.access_token; 25 $.cookie("token", accessToken, { path: "/", expires: 1 }); 26 addOrReplaceHeader(headers, "authorization", "Bearer " + accessToken); 27 $("#getmsg").hide(); 28 } 29 }); 30 31 })
本系列使用记录到此,有用到的再补充,有不对的地方希望大家帮忙指正修改,感谢!
以上是关于Web API使用记录系列OAuth授权与身份校验的主要内容,如果未能解决你的问题,请参考以下文章