學習總結之 WebApi 用戶登陸和匿名登陸,及權限驗證

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

 

WebApi登錄與身份驗證git

由於在調用接口的時候都必須傳sessionKey參數過去,因此必須先登陸驗證身份。github

若是是已註冊用戶則帳號登錄,得到其身份標識的 sessionkey,若是是非帳戶用戶則能夠匿名登錄,要輸入用戶IP地址或者和客戶端設備號等以得到sessionkey,而後能夠去註冊。web

 

 

 

#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。api

 

    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都將擁有身份驗證功能session

 

若是是須要管理員權限才能請求的數據的話,那麼咱們再定義一個 SessionValidateAdminAttribute 來作管理員的身份驗證,在須要管理員權限才能請求的控制器上加上[SessionValidateAdminAttribute ],則這個控制器下面全部Action都只有經過身份驗證的管理員纔有權限請求。cors

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: "*")] 的說明,ide

詳情查看: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

 

 

此隨筆乃本人學習工做記錄,若有疑問歡迎在下面評論,轉載請標明出處。

若是對您有幫助請動動鼠標右下方給我來個贊,您的支持是我最大的動力。

 2017-11 代碼及數據庫文件已經上傳至 https://github.com/huangenai/WebAPI

相關文章
相關標籤/搜索