随着移动互联网的发展,webapi的应用越来越广泛,本文是笔者总结的webapi的认证校验案例,欢迎指出
案例分为两个功能:
1、用户登录,传入账号和密码到api服务器,然后服务器使用FormsAuthenticationTicket作为身份令牌处理
2、正式操作数据,传入登录是服务器返回的令牌数据到api服务器,服务器对令牌进行校验返回结果信息
FormsAuthenticationTicket是微软提供给我们开发人员使用,做身份认证使用的,通过认证,我们可以把关键信息存储到服务器。
具体案例
一、api.html页面,用于测试调用api接口
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title></title> 6 <script src="Scripts/jquery-1.10.2.min.js"></script> 7 <script> 8 function Login() { 9 alert("数据获取中") 10 $.ajax({ 11 cache: true, 12 type: "POST", 13 url: "/api/Account/Login", 14 data: $('#formLogin').serialize(),// 你的formid 15 async: false, 16 beforeSend: function (request) { 17 request.setRequestHeader("token", $("#token").val()); 18 }, 19 error: function (request) { 20 alert("Connection error"); 21 }, 22 success: function (data) { 23 alert("数据获取成功" + data["token"]) 24 $("#token").val(data["token"]); 25 26 alert($("#token").val()) 27 } 28 }); 29 } 30 function Work() { 31 alert("数据获取中") 32 alert($("#token").val()); 33 $.ajax({ 34 cache: true, 35 type: "POST", 36 url: "/api/Work/GetData", 37 data: $('#formWork').serialize(),// 你的formid 38 async: false, 39 beforeSend: function (request) { 40 request.setRequestHeader("token", $("#token").val()); 41 }, 42 error: function (request) { 43 alert(" "); 44 }, 45 success: function (data) { 46 alert("数据获取成功") 47 alert(data["state"]) 48 } 49 }); 50 51 52 } 53 </script> 54 </head> 55 <body> 56 <div id="token"></div> 57 登录测试(Account) 58 <form id="formLogin" method="post"> 59 <table> 60 <tr><td> loginName: </td><td><input type="text" name="loginName" /></td></tr> 61 <tr><td>password:</td><td><input type="text" name="password" /></td></tr> 62 </table> 63 <input type="button" onclick="Login()" value="登录" /> 64 </form> 65 登录测试(Account) 66 <form id="formWork" method="post"> 67 <table> 68 <tr><td> loginName: </td><td><input type="text" name="loginName" /></td></tr> 69 70 </table> 71 <input type="button" onclick="Work()" value="登录" /> 72 </form> 73 </body> 74 </html>
二、登录控制器
1 namespace _01WebApi.Controllers 2 { 3 public class AccountController : ApiController 4 { 5 [AcceptVerbs("POST", "GET")] 6 public HttpResponseMessage Login([FromBody]GetDataModel getData) 7 { 8 HttpResponseMessage result; 9 string returnValue = ""; 10 try 11 { 12 //生成票据 13 string loginName =getData.loginName; 14 string password = getData.password; 15 FormsAuthenticationTicket token = new FormsAuthenticationTicket(0, loginName, DateTime.Now, 16 DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", loginName, password), 17 FormsAuthentication.FormsCookiePath); 18 //返回登录结果、用户信息、用户验证票据信息 19 var Token = FormsAuthentication.Encrypt(token); 20 21 22 File.WriteAllText("d:/loginName" + "_Login.txt", Token); 23 24 returnValue = "{"token":"" + Token + ""}"; 25 26 result = new HttpResponseMessage { Content = new StringContent(returnValue, Encoding.GetEncoding("UTF-8"), "application/json") };//这里是去掉反斜杠再放回出去,json就只剩下双引号。 27 return result; 28 29 } 30 catch (Exception ex) 31 { 32 returnValue = ex.Message.ToString().Replace(" ", "").Replace(" ", ""); 33 } 34 //这里是去掉反斜杠再放回出去,json就只剩下双引号。 35 result = new HttpResponseMessage { Content = new StringContent(CreateMessage(0, returnValue), Encoding.GetEncoding("UTF-8"), "application/json") }; 36 return result; 37 } 38 /// <summary> 39 /// 返回参数 40 /// </summary> 41 /// <param name="State">状态 0 失败 1 成功</param> 42 /// <param name="Msg">信息</param> 43 /// <returns></returns> 44 public static string CreateMessage(int State, string Msg) 45 { 46 string str = "{"state":"" + State + "","msg":"" + Msg + ""}"; 47 return str; 48 } 49 } 50 public class GetDataModel 51 { 52 53 public string loginName { get; set; } 54 public string password { get; set; } 55 56 57 } 58 59 }
三、获取数据控制器
1 namespace _01WebApi.Controllers 2 { 3 public class WorkController : ApiController 4 { 5 [AcceptVerbs("POST", "GET")] 6 [SupportFilter] 7 public HttpResponseMessage GetData([FromBody]GetDataModel getData) 8 { 9 HttpResponseMessage result; 10 string returnValue = ""; 11 try 12 { 13 14 returnValue = "{"state":"获取数据成功"}"; 15 16 result = new HttpResponseMessage { Content = new StringContent(returnValue, Encoding.GetEncoding("UTF-8"), "application/json") };//这里是去掉反斜杠再放回出去,json就只剩下双引号。 17 return result; 18 19 } 20 catch (Exception ex) 21 { 22 returnValue = ex.Message.ToString().Replace(" ", "").Replace(" ", ""); 23 } 24 //这里是去掉反斜杠再放回出去,json就只剩下双引号。 25 result = new HttpResponseMessage { Content = new StringContent(CreateMessage(0, returnValue), Encoding.GetEncoding("UTF-8"), "application/json") }; 26 return result; 27 } 28 /// <summary> 29 /// 返回参数 30 /// </summary> 31 /// <param name="State">状态 0 失败 1 成功</param> 32 /// <param name="Msg">信息</param> 33 /// <returns></returns> 34 public static string CreateMessage(int State, string Msg) 35 { 36 string str = "{"state":"" + State + "","msg":"" + Msg + ""}"; 37 return str; 38 } 39 } 40 }
四、在控制器上增加自定义特性来校验令牌数据
1 namespace _01WebApi.Common 2 { 3 public class SupportFilter : AuthorizeAttribute 4 { 5 //重写基类的验证方式,加入我们自定义的Ticket验证 6 public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) 7 8 { 9 //url获取token 10 var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase; 11 //获取用户提交的token数据,用于和服务器数据进行对比,来判定用户是否有效 12 string token = content.Request.Headers["token"].ToString(); 13 14 if (!string.IsNullOrEmpty(token)) 15 { 16 //解密用户ticket,并校验用户名密码是否匹配 17 if (ValidateTicket(token)) 18 { 19 base.IsAuthorized(actionContext); 20 } 21 else 22 { 23 HandleUnauthorizedRequest(actionContext); 24 } 25 } 26 //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401 27 else 28 { 29 var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); 30 bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); 31 if (isAnonymous) base.OnAuthorization(actionContext); 32 else HandleUnauthorizedRequest(actionContext); 33 } 34 } 35 36 //校验用户名密码(对Session匹配,或数据库数据匹配) 37 private bool ValidateTicket(string encryptToken) 38 { 39 //解密Ticket,并且获取UserData的值 40 var strTicket = FormsAuthentication.Decrypt(encryptToken).UserData; 41 42 //从Ticket里面获取用户名和密码 43 var index = strTicket.IndexOf("&"); 44 string loginName = strTicket.Substring(0, index); 45 string password = strTicket.Substring(index + 1); 46 47 //获取存储在服务器上面的token数据 48 string token = File.ReadAllText("d:/loginName" + "_Login.txt"); 49 if (token == null) 50 { 51 return false; 52 } 53 //对比服务器中的令牌和传入的是否相等 54 if (token.ToString() == encryptToken) 55 { 56 return true; 57 } 58 59 return false; 60 61 } 62 } 63 }