WebApi用户登录验证及服务器端用户状态存取
? ?最近項目需要給手機端提供數據,采用WebApi的方式,之前的權限驗證設計不是很好,這次采用的是Basic基礎認證。
1、常見的認證方式
? ?我們知道,asp.net的認證機制有很多種。對于WebApi也不例外,常見的認證方式有
- FORM身份驗證
- 集成WINDOWS驗證
- Basic基礎認證
- Digest摘要認證
2、Basic基礎認證原理
? ?我們知道,認證的目的在于安全,那么如何能保證安全呢?常用的手段自然是加密。Basic認證也不例外,主要原理就是加密用戶信息,生成票據,每次請求的時候將票據帶過來驗證。這樣說可能有點抽象,我們詳細分解每個步驟:
?這個基本的原理。下面就按照這個原理來看看每一步的代碼如何實現。
3、Basic基礎認證的代碼示例
? ? 創建緩存類,存儲用戶狀態信息CacheManager類
?
public class CacheManager{private static Dictionary<String, Object> cache = null;private static CacheManager cacheManager =null;/// <summary>/// 程序運行時,創建一個靜態只讀的進程輔助對象/// </summary>private static readonly object _object = new object();/// <summary>/// Make sure the class is singleton so only one instance is shared by all. /// </summary>private CacheManager(){cache = new Dictionary<string, object>();}/// <summary>/// Get the singleton instance./// </summary>/// <returns></returns>public static CacheManager instance(){//先判斷實例是否存在,不存在再加鎖處理if (cacheManager == null){//在同一時刻加了鎖的那部分程序只有一個線程可以進入,lock (_object){//如實例不存在,則New一個新實例,否則返回已有實例if (cacheManager == null){cacheManager = new CacheManager();}}}return cacheManager;}/// <summary>/// 添加用戶信息/// </summary>/// <param name="key"></param>/// <param name="value"></param>public void add(String key, Object value){if (!cache.ContainsKey(key))cache.Add(key, value);else{remove(key);cache.Add(key, value);}}/// <summary>/// 刪除用戶狀態信息/// </summary>/// <param name="key"></param>public void remove(String key){cache.Remove(key);}/// <summary>/// 初使化緩存/// </summary>public void invalidateCache(){cache = new Dictionary<string, object>();}/// <summary>/// 獲取用戶狀態信息/// </summary>/// <param name="key"></param>/// <returns></returns>public object get(String key){Object obj;if (cache.ContainsKey(key))cache.TryGetValue(key,out obj);else{obj = null;}return obj;}}在App_Start文件下創建票據認識類RequestAuthorizeAttribute
?
public class RequestAuthorizeAttribute : AuthorizeAttribute{CacheManager cache = CacheManager.instance();//重寫基類的驗證方式,加入我們自定義的Ticket驗證public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext){//從http請求的頭里面獲取身份驗證信息,驗證是否是請求發起方的ticketvar authorization = actionContext.Request.Headers.Authorization;if ((authorization != null) && (authorization.Parameter != null)){//解密用戶ticket,并校驗用戶名密碼是否匹配var encryptTicket = authorization.Parameter;if (ValidateTicket(encryptTicket)){base.IsAuthorized(actionContext);}else{HandleUnauthorizedRequest(actionContext);}}//如果取不到身份驗證信息,并且不允許匿名訪問,則返回未驗證401else{var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);if (isAnonymous) base.OnAuthorization(actionContext);else HandleUnauthorizedRequest(actionContext);}}//校驗用戶名密碼private bool ValidateTicket(string encryptTicket){//解密Ticketvar strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;//從Ticket里面獲取用戶名和密碼var index = strTicket.IndexOf("&");string strUser = strTicket.Substring(0, index);string strPwd = strTicket.Substring(index + 1);//服務器端判斷用戶信息object objUmodel = cache.get(strUser);if (objUmodel != null){UserModel u = (UserModel)objUmodel;if (u.UserPwd.Equals(strPwd))return true;elsecache.remove(strUser);return false;}else{return false;}}}
在公共方法中創建獲取票據方法
/// <summary>/// 獲取票據/// </summary>/// <param name="ticketName">票證名稱</param>/// <param name="timeState">票證過期時間</param>/// <param name="userData">票證數據</param>/// <returns></returns>public static FormsAuthenticationTicket GetTicket(string ticketName, int timeState, string userData){FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, ticketName, DateTime.Now,DateTime.Now.AddMinutes(timeState),true, string.Format("{0}&{1}", ticketName, userData),FormsAuthentication.FormsCookiePath);return ticket;}用戶登錄時,存入票據
[HttpPost][AllowAnonymous]public object UserLogin([FromBody] UserModel model){Int32 sysRole = 0;Message msg = new Message() { Content = "登錄失敗,請重新登錄!" };if (model==null || string.IsNullOrEmpty(model.UserCode) || string.IsNullOrEmpty(model.UserPwd)){msg.Flag = false;return msg;}string EncryptPwd = PasswordUtility.Md5To32(model.UserPwd);var userModel = user.UserModelByLogin(model.UserCode, EncryptPwd, sysRole);if (userModel != null && userModel.ID > 0){msg.Flag = true;msg.Content = "登錄成功!";FormsAuthenticationTicket ticket = Common.GetTicket(userModel.UserCode, timeState, EncryptPwd);//返回登錄結果、用戶信息、用戶驗證票據信息var oUser = new UserModel { Flag = true,UserCode= userModel.UserCode,UserImg= userModel.UserImg, UserName = userModel.UserName, UserPwd = EncryptPwd, Ticket = FormsAuthentication.Encrypt(ticket) };msg.ApiData = oUser;cache.add(model.UserCode, oUser);}else{msg.Flag = false;msg.Data = "";}return msg;}?
4、WebApi跨域調用方法
因為WebApi涉及到跨域請求,所以在WebConfig中需要加入一段代碼,解決跨域問題,Authorization是向http的head里面加入請求票據,否則瀏覽器請求不成功。
<httpProtocol><customHeaders><add name="Access-Control-Allow-Origin" value="*" /><add name="Access-Control-Allow-Headers" value=" Origin,Content-Type, Accept,Authorization" /><add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /></customHeaders></httpProtocol>
5、Web頁面調用WebApi方法,使用Ajax調用方法
var Ticket;$(function () {$.ajax({type: "post",url: url + "/UserLogin",data: { UserCode: '1002', UserPwd: '123456' },datatype: 'json',success: function (data, status) {if (status == "success") {debugger;if (!data.Flag) {alert("登錄失敗");return;}alert("登錄成功");//登錄成功之后將用戶名和用戶票據帶到主界面Ticket = data.ApiData.Ticket;$("#hdTicket").val(Ticket);}},error: function (e) {},complete: function () {}});});function myfunction() {$.ajax({type: "get",url: url + '/GetLoginOut?uid=1002',datatype:'json',beforeSend: function (request) {alert('beforesend:' + Ticket);//發送ajax請求之前向http的head里面加入驗證信息request.setRequestHeader('Authorization', 'BasicAuth ' + Ticket);},//xhrFields: {// withCredentials: true//},//crossDomain: true,success: function (data) {alert('success:' + data);},error: function (data) {console.log(data);alert('error:' + data);}});}
? ?跨域請求參考地址:https://www.cnblogs.com/cdemo/p/5158663.html
? 原為參考地址:https://www.cnblogs.com/landeanfen/p/5287064.html
轉載于:https://www.cnblogs.com/personblog/p/8535204.html
總結
以上是生活随笔為你收集整理的WebApi用户登录验证及服务器端用户状态存取的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20165334 《java程序设计》第
- 下一篇: 图像滤镜艺术--编码基础(Photosh