學習總結之 WebApi 用戶登錄和匿名登錄,及許可權驗證

来源:http://www.cnblogs.com/huangenai/archive/2016/04/23/5253709.html
-Advertisement-
Play Games

近些天,看了一些博客園大牛關於webApi項目的的文章,也有請教師兄一些問題,自己做了個Demo試了試,收穫甚多。感謝感謝,下麵是我一些學習的總結,如若有錯的地方請多多指教!! WebApi登陸與身份驗證 因為在調用介面的時候都必須傳sessionKey參數過去,所以必須先登錄驗證身份。 如果是已註 ...


近些天,看了一些博客園大牛關於webApi項目的的文章,也有請教師兄一些問題,自己做了個Demo試了試,收穫甚多。感謝感謝,下麵是我一些學習的總結,如若有錯的地方請多多指教!!

 

WebApi登陸與身份驗證

因為在調用介面的時候都必須傳sessionKey參數過去,所以必須先登錄驗證身份。

如果是已註冊用戶則賬號登陸,獲得其身份標識的 sessionkey,如果是非賬戶用戶則可以匿名登陸,要輸入用戶IP地址或者和客戶端設備號等以獲得sessionkey,然後可以去註冊。

 

 

 

#region  登錄API
        /// <summary>
        /// 登錄API (賬號登陸)
        /// </summary>
        /// <param name="phone">登錄帳號手機號</param>
        /// <param name="hashedPassword">加密後的密碼,這裡避免明文,客戶端加密後傳到API端</param>
        /// <param name="deviceType">客戶端的設備類型</param>
        /// <param name="clientId">客戶端識別號, 一般在APP上會有一個客戶端識別號</param>
        /// <returns></returns>
        [Route("account/login")]
        public SessionObject Login(string phone, string hashedPassword, int deviceType = 0, string clientId = "") {
            if (string.IsNullOrEmpty(phone))
                throw new ApiException("用戶名不能為空。", "RequireParameter_userphone");
            if (string.IsNullOrEmpty(hashedPassword))
                throw new ApiException("hashedPassword 不能為空.", "RequireParameter_hashedPassword");

            int timeout = 60;

            var nowUser = _authenticationService.GetUserByPhone(phone);
            if (nowUser == null)
                throw new ApiException("帳戶不存在", "Account_NotExits");

            #region 驗證密碼
            if (!string.Equals(nowUser.Password, hashedPassword)) {
                throw new ApiException("錯誤的密碼", "Account_WrongPassword");
            }
            #endregion

            if (!nowUser.IsActive)
                throw new ApiException("用戶處於非活動狀態.", "InactiveUser");

            UserDevice existsDevice = _authenticationService.GetUserDevice(nowUser.UserId, deviceType);
            
            if (existsDevice == null) {
                string passkey = MD5CryptoProvider.GetMD5Hash(nowUser.UserId + nowUser.Phone + DateTime.UtcNow+ Guid.NewGuid());
                existsDevice = new UserDevice() {
                    UserId = nowUser.UserId,
                    CreateTime = DateTime.UtcNow,
                    ActiveTime = DateTime.UtcNow,
                    ExpiredTime = DateTime.UtcNow.AddMinutes(timeout),
                    DeviceType = deviceType,
                    SessionKey = passkey
                };
                _authenticationService.AddUserDevice(existsDevice);
            }
            else {
                existsDevice.ActiveTime = DateTime.UtcNow;
                existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes(timeout);
                _authenticationService.UpdateUserDevice(existsDevice);
            }
            nowUser.Password = "";
            return new SessionObject() { SessionKey = existsDevice.SessionKey, LogonUser = nowUser };
        }
        #endregion
登錄API
        #region 匿名登陸
        /// <summary>
        /// 匿名登陸
        /// </summary>
        /// <param name="ip">用戶ip地址</param>
        /// <param name="deviceType">設備類型</param>
        /// <param name="clientId">客戶端識別號</param>
        /// <returns></returns>
        [Route("account/AnonymousLogin")]
        public SessionObject1 AnonymousLogin(string ip, int deviceType = 0, string clientId = "")
        {
            if (string.IsNullOrEmpty(ip))throw new ApiException("ip地址不能為空。", "RequireParameter_ip");

            int timeout = 60;

            UserDevice existsDevice = _authenticationService.GetUserDevice(ip, deviceType);
            // Session.QueryOver<UserDevice>().Where(x => x.AccountId == nowAccount.Id && x.DeviceType == deviceType).SingleOrDefault();
            if (existsDevice == null) {
                string passkey = MD5CryptoProvider.GetMD5Hash(ip+DateTime.UtcNow + Guid.NewGuid());
                existsDevice = new UserDevice() {
                    IP = ip,
                    CreateTime = DateTime.UtcNow,
                    ActiveTime = DateTime.UtcNow,
                    ExpiredTime = DateTime.UtcNow.AddMinutes(timeout),
                    DeviceType = deviceType,
                    SessionKey = passkey
                };
                _authenticationService.AddUserDevice(existsDevice);
            }
            else {
                existsDevice.ActiveTime = DateTime.UtcNow;
                existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes(timeout);
                _authenticationService.UpdateUserDevice(existsDevice);
            }
            return new SessionObject1() { SessionKey = existsDevice.SessionKey, Ip=ip };
        }
    
        #endregion
匿名登陸

 

身份信息的認證是通過Web API 的 ActionFilter來實現的,所有需要身份驗證的API請求都會要求客戶端傳一個SessionKey。

在這裡我們通過一個自定義的SessionValidateAttribute來做客戶端的身份驗證, 其繼承自 System.Web.Http.Filters.ActionFilterAttribute。

 

    public class SessionValidateAttribute : System.Web.Http.Filters.ActionFilterAttribute
    {
        public const string SessionKeyName = "SessionKey";
        public const string LogonUserName = "LogonUser";

        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            var qs = HttpUtility.ParseQueryString(filterContext.Request.RequestUri.Query);
            string sessionKey = qs[SessionKeyName];

            if (string.IsNullOrEmpty(sessionKey))
            {
                throw new ApiException("無效 Session.", "InvalidSession");
            }

            IAuthenticationService authenticationService = new AuthenticationService();//IocManager.Intance.Reslove<IAuthenticationService>();

            //驗證用戶session
            var userSession = authenticationService.GetUserDevice(sessionKey);

            if (userSession == null)
            {
                throw new ApiException("無此 sessionKey", "RequireParameter_sessionKey");
            }
            else
            {
                //todo: 加Session是否過期的判斷
                if (userSession.ExpiredTime < DateTime.UtcNow)
                    throw new ApiException("session已過期", "SessionTimeOut");

                var logonUser = authenticationService.GetUser(userSession.UserId);
                if (logonUser != null)
                {
                    filterContext.ControllerContext.RouteData.Values[LogonUserName] = logonUser;
                    SetPrincipal(new UserPrincipal<int>(logonUser));
                }
                userSession.ActiveTime = DateTime.UtcNow;
                userSession.ExpiredTime = DateTime.UtcNow.AddMinutes(60);
                authenticationService.UpdateUserDevice(userSession);
            }
        }

        public static void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }
        }
    }
API身份驗證

 

需要身份驗證的apiControler 上加上[sessionValidate],則這個Controller下麵所有Action都將擁有身份驗證功能

 

如果是需要管理員許可權才能請求的數據的話,那麼我們再定義一個 SessionValidateAdminAttribute 來做管理員的身份驗證,在需要管理員許可權才能請求的控制器上加上[SessionValidateAdminAttribute ],則這個控制器下麵所有Action都只有通過身份驗證的管理員才有許可權請求。

public class SessionValidateAdminAttribute : System.Web.Http.Filters.ActionFilterAttribute {
        public const string SessionKeyName = "SessionKey";
        public const string LogonUserName = "LogonUser";

        public override void OnActionExecuting(HttpActionContext filterContext) {
            var qs = HttpUtility.ParseQueryString(filterContext.Request.RequestUri.Query);
            string sessionKey = qs[SessionKeyName];

            if (string.IsNullOrEmpty(sessionKey)) {
                throw new ApiException("無效 Session.", "InvalidSession");
            }

            IAuthenticationService authenticationService = new AuthenticationService();//IocManager.Intance.Reslove<IAuthenticationService>();

            //驗證用戶session
            var userSession = authenticationService.GetUserDevice(sessionKey);

            if (userSession == null) {
                throw new ApiException("無此 sessionKey", "RequireParameter_sessionKey");
            }
            else {
                //todo: 加Session是否過期的判斷
                if (userSession.ExpiredTime < DateTime.UtcNow)
                    throw new ApiException("session已過期", "SessionTimeOut");

                var logonUser = authenticationService.GetUser(userSession.UserId);

                if (logonUser == null) {
                    throw new ApiException("無此用戶", "Invalid_User");
                }
                else
                {
                    if (logonUser.Permissions == 1)
                    {
                        filterContext.ControllerContext.RouteData.Values[LogonUserName] = logonUser;
                        SessionValidateAttribute.SetPrincipal(new UserPrincipal<int>(logonUser));
                    }
                    else
                    {
                        throw new ApiException("用戶無許可權", "No permissions");
                    }
                }
                userSession.ActiveTime = DateTime.UtcNow;
                userSession.ExpiredTime = DateTime.UtcNow.AddMinutes(60);
                authenticationService.UpdateUserDevice(userSession);
            }
        }

    }
SessionValidateAdminAttribute

關於:[EnableCors(origins: "*", headers: "*", methods: "*")] 的說明,

詳情查看:http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-05.html

 

關於用戶過期時間:每次調用介面的時候 會自動更新sessionKey的過期時間,如果長時間未更新,則下次訪問時會過期,則需要重新登陸。

 

加入身份驗證後的 UserControler 

[EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/Users"), SessionValidate, WebApiTracker] 
    public class UsersController : ApiController
    {
        private  readonly IUsers _users=new UsersImpl();
        #region 根據用戶ID獲得用戶信息
        /// <summary>
        /// 根據用戶ID獲得用戶信息(獲得數據)
        /// </summary>
        /// <param name="sessionKey">sessionKey</param>
        /// <param name="id">用戶id</param>
        /// <returns>result</returns>
        public ApiResult<Users> GetUserById( string sessionKey,int  id)
        {
            Users modelUsers = _users.GetUserByUsersId(id);
            if (modelUsers != null)
            {
                return new ApiResult<Users>("1","獲取用戶信息成功",modelUsers);
            }
            else return new ApiResult<Users>("0","無此用戶信息",null);
        }
        #endregion

        /// <summary>
        /// 新用戶註冊(增加數據)
        /// </summary>
        /// <param name="modelUsers"></param>
        /// <returns>result</returns>
        [HttpPost, Route("api/UserRegistration")]
        public ApiResult<bool> UserRegistration(string sessionKey, AddUserRq modelUsers)
        {
            Users usersModel=new Users();
            usersModel.IsActive = true;
            usersModel.Password = modelUsers.Password;
            usersModel.Permissions = 2;
            usersModel.Phone = modelUsers.Phone;
            usersModel.Sex = modelUsers.Sex;
            usersModel.TrueName = modelUsers.TrueName;
            usersModel.UserName = modelUsers.UserName;
            return _users.RegistrationNewUsers(usersModel);
        }
    }
UsersControllers

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.tracepath tracepath追蹤出到指定的目的地址的網路路徑,並給出在路徑上的每一跳(hop)。如果你的網路有問題或是慢了,tracepath可以查出網路在哪裡斷了或是慢了。 命令格式: traceroute[-dFlnrvx][-f<存活數值>][-g<網關>...][-i<網路界面 ...
  • 在安裝apache之前需要準備一些必要的依賴包 gcc安裝: gcc-c++安裝: apr安裝: 下載包:apr-1.5.2.tar.gz,然後tar解壓縮到任意目錄下.然後進入解壓縮後的目錄下進行如下編譯: apr-util安裝: 下載包:apr-util-1.5.4,同樣tar解壓縮到任意目錄下 ...
  • 設置終端的字體顏色 如圖,打開終端然後,選擇偏好設置,再選擇描述文件,再視窗左側可以選擇系統配置好的,或者你也可以自定義,最後別忘了把你的配置設置成預設就行 Vim語法高亮設置 只需要找到vimrc配置文件就行,在終端輸入下麵的指令,就可以打開配置文件 cp /usr/share/vim/vimrc ...
  • 系統中對應的文件是/etc/inittab # Default runlevel. The runlevels used by RHS are:# 0 - halt (Do NOT set initdefault to this)# 1 - Single user mode# 2 - Multius ...
  • 先查看一下系統版本,本例採用的操作系統是CentOS 6.5: 如果你是初裝之後的操作系統,那麼有可能wget這個組件是不存在的,所以你要安裝一下它,這樣才可以讓你從網上down下你要的安裝包: 上面這幅圖是檢查一下你是否安裝過wget組件,如果沒有的話用下麵這條語句安裝一下它即可: 當然如果你不檢 ...
  • 在請求WebApi 的時候,我們更想知道在請求數據的時候,調用了哪個介面傳了什麼參數過來,調用這個Action花了多少時間,有沒有人惡意請求。我們可以通過記錄日誌,對Action進行優化,可以通過日誌追蹤是哪個用戶或ip惡意請求。 在項目中引用log4net.dll 定義一個WebApiMonito ...
  • ahsupermarketshopping AH外貿公司英文企業網站源碼 http://www.51aspx.com/Code/AHForeignTradeCompanyrayxietongoa RayOA協同辦公服務平臺源碼 http://www.51aspx.com/code/RayXieTon ...
  • 昨天是周五太放鬆了,晚上沒有加班只顧著放鬆,玩了一晚上,今天又是睡了一上午,沒有學習。這下放鬆過分了沒有總結,也沒有完成任務。今天來總結一下昨天的學習成果。 昨天設計的資料庫今天老大點評了一下發現問題確實很多。比如用戶表和許可權表的拆分問題,是否應該拆分取決於許可權的使用頻率。使用頻率高時因該拆分。 對 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...