近些天,看了一些博客园大牛关于webApi项目的的文章,也有请教师兄一些问题,自己做了个Demo试了试,收获甚多。感谢感谢,下面是我一些学习的总结,如若有错的地方请多多指教!!

近些天,看了一些博客园大牛关于webApi项目的的文章,也有请教师兄一些问题,自己做了个Demo试了试,收获甚多。感谢感谢,下面是我一些学习的总结,如若有错的地方请多多指教!!

上一篇: 【WEB API项目实战干货系列】- 接口文档与在线测试

 

WebApi登陆与身份验证

这篇我们主要来介绍我们如何在API项目中完成API的登录及身份认证.
所以这篇会分为两部分, 登录API, API身份验证.

WebApi登陆与身份验证

因为在调用接口的时候都必须传sessionKey参数过去,所以必须先登录验证身份。

这一篇的主要原理是: API会提供一个单独的登录API,
通过用户名,密码来产生一个SessionKey, SessionKey具有过期时间的特点,
系统会记录这个SessionKey,
在后续的每次的API返回的时候,客户端需带上这个Sessionkey,
API端会验证这个SessionKey.

因为在调用接口的时候都必须传sessionKey参数过去,所以必须先登录验证身份。

如果是已注册用户则账号登陆,获得其身份标识的
sessionkey,如果是非账户用户则可以匿名登陆,要输入用户IP地址或者和客户端设备号等以获得sessionkey,然后可以去注册。

登录API

我们先来看一下登录API的方法签名

图片 1

 

SessionObject是登录之后,给客户端传回的对象,
里面包含了SessionKey及当前登录的用户的信息

图片 2

这里每次的API调用,都需要传SessionKey过去,
SessionKey代表了用户的身份信息,及登录过期信息。

 

登录阶段生成的SessionKey我们需要做保存,存储到一个叫做UserDevice的对象里面,
从语意上可以知道用户通过不同的设备登录会产生不同的UserDevice对象.

图片 3

 

最终的登录代码如下:

[RoutePrefix("api/accounts")]    public class AccountController : ApiController    {        private readonly IAuthenticationService _authenticationService = null;        public AccountController()        {            //this._authenticationService = IocManager.Intance.Reslove<IAuthenticationService>();        }        [HttpGet]        public void AccountsAPI()        {        }        /// <summary>        /// 登录API        /// </summary>        /// <param name="loginIdorEmail">登录帐号(邮箱或者其他LoginID)</param>        /// <param name="hashedPassword">加密后的密码,这里避免明文,客户端加密后传到API端</param>        /// <param name="deviceType">客户端的设备类型</param>        /// <param name="clientId">客户端识别号, 一般在APP上会有一个客户端识别号</param>        /// <remarks>其他的登录位置啥的,是要客户端能传的东西,都可以在这里扩展进来</remarks>        /// <returns></returns>        [Route("account/login")]        public SessionObject Login(string loginIdorEmail, string hashedPassword, int deviceType = 0, string clientId = "")        {            if (string.IsNullOrEmpty(loginIdorEmail))                throw new ApiException("username can't be empty.", "RequireParameter_username");            if (string.IsNullOrEmpty(hashedPassword))                throw new ApiException("hashedPassword can't be empty.", "RequireParameter_hashedPassword");            int timeout = 60;            var nowUser = _authenticationService.GetUserByLoginId(loginIdorEmail);            if (nowUser == null)                throw new ApiException("Account Not Exists", "Account_NotExits");            #region Verify Password            if (!string.Equals(nowUser.Password, hashedPassword))            {                throw new ApiException("Wrong Password", "Account_WrongPassword");            }            #endregion            if (!nowUser.IsActive)                throw new ApiException("The user is inactive.", "InactiveUser");            UserDevice existsDevice = _authenticationService.GetUserDevice(nowUser.UserId, deviceType);// Session.QueryOver<UserDevice>().Where(x => x.AccountId == nowAccount.Id && x.DeviceType == deviceType).SingleOrDefault();            if (existsDevice == null)            {                string passkey = MD5CryptoProvider.GetMD5Hash(nowUser.UserId + nowUser.LoginName + DateTime.UtcNow.ToString() + Guid.NewGuid().ToString;                existsDevice = new UserDevice()                {                    UserId = nowUser.UserId,                    CreateTime = DateTime.UtcNow,                    ActiveTime = DateTime.UtcNow,                    ExpiredTime = DateTime.UtcNow.AddMinutes,                    DeviceType = deviceType,                    SessionKey = passkey                };                _authenticationService.AddUserDevice(existsDevice);            }            else            {                existsDevice.ActiveTime = DateTime.UtcNow;                existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes;                _authenticationService.UpdateUserDevice(existsDevice);            }            nowUser.Password = "";            return new SessionObject() { SessionKey = existsDevice.SessionKey, LogonUser = nowUser };        }    }

 

如果是已注册用户则账号登陆,获得其身份标识的
sessionkey,如果是非账户用户则可以匿名登陆,要输入用户IP地址或者和客户端设备号等以获得sessionkey,然后可以去注册。

图片 4图片 5

API身份验证

身份信息的认证是通过Web API 的 ActionFilter来实现的,
每各需要身份验证的API请求都会要求客户端传一个SessionKey在URL里面丢过来。

在这里我们通过一个自定义的SessionValidateAttribute来做客户端的身份验证,
其继承自 System.Web.Http.Filters.ActionFilterAttribute,
把这个Attribute加在每个需要做身份验证的ApiControler上面,这样该
Controller下面的所有Action都将拥有身份验证的功能,
这里会存在如果有少量的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("Invalid Session.", "InvalidSession");            }            IAuthenticationService authenticationService = IocManager.Intance.Reslove<IAuthenticationService>();            //validate user session            var userSession = authenticationService.GetUserDevice(sessionKey);            if (userSession == null)            {                throw new ApiException("sessionKey not found", "RequireParameter_sessionKey");            }            else            {                //todo: 加Session是否过期的判断                if (userSession.ExpiredTime < DateTime.UtcNow)                    throw new ApiException("session expired", "SessionTimeOut");                var logonUser = authenticationService.GetUser(userSession.UserId);                if (logonUser == null)                {                    throw new ApiException("User not found", "Invalid_User");                }                else                {                    filterContext.ControllerContext.RouteData.Values[LogonUserName] = logonUser;                    SetPrincipal(new UserPrincipal<int>(logonUser));                }                userSession.ActiveTime = DateTime.UtcNow;                userSession.ExpiredTime = DateTime.UtcNow.AddMinutes(60);                authenticationService.UpdateUserDevice(userSession);            }        }        private void SetPrincipal(IPrincipal principal)        {            Thread.CurrentPrincipal = principal;            if (HttpContext.Current != null)            {                HttpContext.Current.User = principal;            }        }    }

 

OnActionExcuting方法:

这个是在进入某个Action之前做检查,
这个时候我们刚好可以同RequestQueryString中拿出SessionKey到UserDevice表中去做查询,来验证Sessionkey的真伪,
以达到身份验证的目的。

 

用户的过期时间:

在每个API访问的时候,会自动更新Session(也就是UserDevice)的过期时间,
以保证SessionKey不会过期,如果长时间未更新,则下次访问会过期,需要重新登录做处理。

 

Request.IsAuthented:

上面代码的最后一段SetPrincipal就是来设置我们线程上下文及HttpContext上下文中的用户身份信息,
在这里我们实现了我们自己的用户身份类型

public class UserIdentity<TKey> : IIdentity    {        public UserIdentity(IUser<TKey> user)        {            if (user != null)            {                IsAuthenticated = true;                UserId = user.UserId;                Name = user.LoginName.ToString();                DisplayName = user.DisplayName;            }        }        public string AuthenticationType        {            get { return "CustomAuthentication"; }        }        public TKey UserId { get; private set; }        public bool IsAuthenticated { get; private set; }        public string Name { get; private set; }        public string DisplayName { get; private set; }    }    public class UserPrincipal<TKey> : IPrincipal    {        public UserPrincipal(UserIdentity<TKey> identity)        {            Identity = identity;        }        public UserPrincipal(IUser<TKey> user)            : this(new UserIdentity<TKey>        {        }        /// <summary>        ///         /// </summary>        public UserIdentity<TKey> Identity { get; private set; }        IIdentity IPrincipal.Identity        {            get { return Identity; }        }        bool IPrincipal.IsInRole(string role)        {            throw new NotImplementedException();        }    }    public interface IUser<T>    {        T UserId { get; set; }        string LoginName { get; set; }        string DisplayName { get; set; }    }

这样可以保证我们在系统的任何地方,通过HttpContext.User 或者
System.Threading.Thread.CurrentPrincipal可以拿到当前线程上下文的用户信息,
方便各处使用

 

加入身份认证之后的Product相关API如下:

[RoutePrefix("api/products"), SessionValidate]    public class ProductController : ApiController    {        [HttpGet]        public void ProductsAPI()        { }        /// <summary>        /// 产品分页数据获取        /// </summary>        /// <returns></returns>        [HttpGet, Route("product/getList")]        public Page<Product> GetProductList(string sessionKey)        {            return new Page<Product>();        }        /// <summary>        /// 获取单个产品        /// </summary>        /// <param name="productId"></param>        /// <returns></returns>        [HttpGet, Route("product/get")]        public Product GetProduct(string sessionKey, Guid productId)        {            return new Product() { ProductId = productId };        }        /// <summary>        /// 添加产品        /// </summary>        /// <param name="product"></param>        /// <returns></returns>        [HttpPost, Route("product/add")]        public Guid AddProduct(string sessionKey, Product product)        {            return Guid.NewGuid();        }        /// <summary>        /// 更新产品        /// </summary>        /// <param name="productId"></param>        /// <param name="product"></param>        [HttpPost, Route("product/update")]        public void UpdateProduct(string sessionKey, Guid productId, Product product)        {        }        /// <summary>        /// 删除产品        /// </summary>        /// <param name="productId"></param>        [HttpDelete, Route("product/delete")]        public void DeleteProduct(string sessionKey, Guid productId)        {        }

 

可以看到我们的ProductController上面加了SessionValidateAttribute,
每个Action参数的第一个位置,加了一个string sessionKey的占位,
这个主要是为了让Swagger.Net能在UI上生成测试窗口

图片 6

这篇并没有使用OAuth等授权机制,只是简单的实现了登录授权,这种方式适合小项目使用.

这里也只是实现了系统的登录,API访问安全,并不能保证
API系统的绝对安全,我们可以透过 路由的上的HTTP消息拦截,
拦截到我们的API请求,截获密码等登录信息,
因此我们还需要给我们的API增加SSL证书,实现 HTTPS加密传输。

另外在前几天的有看到结合客户端IP地址等后混合生成
Sessionkey来做安全的,但是也具有一定的局限性,
那种方案合适,还是要根据自己的实际项目情况来确定.

 

由于时间原因,
本篇只是从原理方面介绍了API用户登录与访问身份认证,因为这部分真实的测试设计到数据库交互,
Ioc等基础设施的支撑,所以这篇的代码只能出现在SwaggerUI中,但是无法实际测试接口。在接下来的代码中我会完善这部分.

代码: 代码下载(代码托管在CSDN Code)

图片 4 图片 5

图片 9图片 10

 

#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                throw new ApiException("用户名不能为空。", "RequireParameter_userphone");            if (string.IsNullOrEmpty(hashedPassword))                throw new ApiException("hashedPassword 不能为空.", "RequireParameter_hashedPassword");            int timeout = 60;            var nowUser = _authenticationService.GetUserByPhone;            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,                    DeviceType = deviceType,                    SessionKey = passkey                };                _authenticationService.AddUserDevice(existsDevice);            }            else {                existsDevice.ActiveTime = DateTime.UtcNow;                existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes;                _authenticationService.UpdateUserDevice(existsDevice);            }            nowUser.Password = "";            return new SessionObject() { SessionKey = existsDevice.SessionKey, LogonUser = nowUser };        }        #endregion

 

登录API图片 11图片 12

图片 13图片 14

        #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.IsNullOrEmptythrow 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,                    DeviceType = deviceType,                    SessionKey = passkey                };                _authenticationService.AddUserDevice(existsDevice);            }            else {                existsDevice.ActiveTime = DateTime.UtcNow;                existsDevice.ExpiredTime = DateTime.UtcNow.AddMinutes;                _authenticationService.UpdateUserDevice(existsDevice);            }            return new SessionObject1() { SessionKey = existsDevice.SessionKey, Ip=ip };        }            #endregion
#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

图片 15

图片 16图片 17

身份信息的认证是通过Web API 的
ActionFilter来实现的,所有需要身份验证的API请求都会要求客户端传一个SessionKey。

        #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

在这里我们通过一个自定义的SessionValidateAttribute来做客户端的身份验证,
其继承自 System.Web.Http.Filters.ActionFilterAttribute。

匿名登陆

图片 18图片 19

图片 15

    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身份验证

身份信息的认证是通过Web API 的
ActionFilter来实现的,所有需要身份验证的API请求都会要求客户端传一个SessionKey。

需要身份验证的apiControler
上加上[sessionValidate],则这个Controller下面所有Action都将拥有身份验证功能

在这里我们通过一个自定义的SessionValidateAttribute来做客户端的身份验证,
其继承自 System.Web.Http.Filters.ActionFilterAttribute。

图片 21

 

如果是需要管理员权限才能请求的数据的话,那么我们再定义一个
SessionValidateAdminAttribute
来做管理员的身份验证,在需要管理员权限才能请求的控制器上加上[SessionValidateAdminAttribute],则这个控制器下面所有Action都只有通过身份验证的管理员才有权限请求。

图片 22图片 23

图片 24图片 25

    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;
            }
        }
    }
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);            }        }    }

API身份验证

SessionValidateAdminAttribute

 

图片 26

需要身份验证的apiControler
上加上[sessionValidate],则这个Controller下面所有Action都将拥有身份验证功能

关于:[EnableCors(origins: “*”,
headers: “*”, methods: “*”)] 的说明,

图片 21

详情查看:

 

关于用户过期时间:每次调用接口的时候
会自动更新sessionKey的过期时间,如果长时间未更新,则下次访问时会过期,则需要重新登陆。

如果是需要管理员权限才能请求的数据的话,那么我们再定义一个
SessionValidateAdminAttribute
来做管理员的身份验证,在需要管理员权限才能请求的控制器上加上[SessionValidateAdminAttribute ],则这个控制器下面所有Action都只有通过身份验证的管理员才有权限请求。

加入身份验证后的 UserControler

图片 28图片 29

图片 30图片 31

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);
            }
        }

    }
[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;            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);        }    }

SessionValidateAdminAttribute

UsersControllers

图片 26

此随笔乃本人学习工作记录,如有疑问欢迎在下面评论,转载请标明出处。

关于:[EnableCors(origins: “*”,
headers: “*”, methods: “*”)] 的说明,

如果对您有帮助请动动鼠标右下方给我来个赞,您的支持是我最大的动力。

详情查看:

2017-11 代码及数据库文件已经上传至

 

图片 33

关于用户过期时间:每次调用接口的时候
会自动更新sessionKey的过期时间,如果长时间未更新,则下次访问时会过期,则需要重新登陆。

 

加入身份验证后的 UserControler 

图片 34图片 35

[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
代码及数据库文件已经上传至 

图片 36

相关文章