文档章节

OWIN+AspNet.Identity实现用户认证/登录/注册(MVC)

李朝强
 李朝强
发布于 2015/10/13 19:29
字数 4134
阅读 6608
收藏 9
点赞 4
评论 6

关于AspNet.Identity,参考:http://www.cnblogs.com/shanyou/p/3918178.html

关于OWIN,可以阅读:http://www.cnblogs.com/dudu/p/what-is-owin.html

  OWIN使ASP.NET应用运行在其它平台上称为可能。对ASP.NET程序和IIS进行解耦。我们可以在没有安装IIS的情况下,运行ASP.NET程序。在这里http://katanaproject.codeplex.com/可以下载源码。

  另一个概念就是基于声明(Claim)的认证机制。


什么是Claims-based(基于声明)的认证

    首先,这种机制并非微软特有的,Claims-based认证和授权在国外被广泛使用,包括微软的ADFS,Google,Facebook等。


Claims-based认证的主要特点:

  • 将认证与授权拆分成独立的服务
  • 服务调用者(一般是网站),不需要关注你如何去认证,你用Windows认证也好,用令牌手机短信也好,与我无关。
  • 如果用户成功登录的话,认证服务(假如是QQ) 会返回给我们一个令牌。
  • 令牌当中包含了服务调用者所需要的信息,用户名,以及角色信息等等。
     总的来说就是,我再也不用管你怎么登录,怎么样去拿你有哪些角色了,我只需要把你跳到那个登录站点上,然后它返回给我令牌信息,我从令牌上获取需要的信息来确定你是谁,你拥有什么角色就可以了。


    接下来,我们会使用到两个对象Microsoft.AspNet.Identity.UserManager和Microsoft.AspNet.Identity.Owin.SignInManager,当然,在不使用Microsoft.AspNet.Identity.Owin.SignInManager的情况下,我们依然可以完成认证工作。在这里,我手动创建了两个类,分别集成前两个类。代码如下:


TiKuSignInManager 类:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/******************************************************************************************************************
 * 
 * 
 * 说 明: (版本:Version1.0.0)
 * 作 者:李朝强
 * 日 期:2015/05/19
 * 修 改:
 * 参 考:http://my.oschina.net/lichaoqiang/
 * 备 注:暂无...
 * 
 * 
 * ***************************************************************************************************************/
namespace AspNetIdentity.Models
{
    public class TiKuSignInManager : Microsoft.AspNet.Identity.Owin.SignInManager<TiKuUser, Guid>
    {

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="UserManager"></param>
        /// <param name="AuthenticationManager"></param>
        public TiKuSignInManager(Microsoft.AspNet.Identity.UserManager<TiKuUser, Guid> UserManager, Microsoft.Owin.Security.IAuthenticationManager AuthenticationManager)
            : base(UserManager, AuthenticationManager)
        {

        }

        /// <summary>
        /// 根据用户名密码,验证用户登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="isPersistent"></param>
        /// <param name="shouldLockout"></param>
        /// <returns></returns>
        public override System.Threading.Tasks.Task<Microsoft.AspNet.Identity.Owin.SignInStatus> PasswordSignInAsync(string userName,
                                                                                                                     string password,
                                                                                                                     bool isPersistent,
                                                                                                                     bool shouldLockout)
        {
            return base.PasswordSignInAsync(userName,
                                            password,
                                            isPersistent,
                                            shouldLockout);
        }
    }
}



TiKuUserManager 类:



using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Web;

namespace AspNetIdentity.Models
{
    public class TiKuUserManager : Microsoft.AspNet.Identity.UserManager<TiKuUser, Guid>
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="store"></param>
        public TiKuUserManager(TiKuUserStore store)
            : base(store)
        {
            //采用老的加密程序
            this.PasswordHasher = new OldSystemPasswordHasher();
        }

        /// <summary> 
        /// Use Custom approach to verify password 
        /// </summary> 
        public class OldSystemPasswordHasher : PasswordHasher
        {

            /// <summary>
            /// 对密码进行Hash加密
            /// </summary>
            /// <param name="password"></param>
            /// <returns></returns>
            public override string HashPassword(string password)
            {
                byte[] salt;
                byte[] buffer2;
                if (password == null)
                {
                    throw new ArgumentNullException("password");
                }
                using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8))
                {
                    salt = bytes.Salt;
                    buffer2 = bytes.GetBytes(0x20);
                }
                byte[] dst = new byte[0x31];
                Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
                Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
                return Convert.ToBase64String(dst);
            }

            /// <summary>
            /// 重写验证密码的方法
            /// </summary>
            /// <param name="hashedPassword">加密后的密码</param>
            /// <param name="providedPassword">提供的密码</param>
            /// <returns></returns>
            public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
            {
                byte[] buffer4;
                if (hashedPassword == null)
                {
                    return PasswordVerificationResult.Failed;
                }
                if (string.IsNullOrEmpty(providedPassword))
                {
                    throw new ArgumentNullException("providedPassword");
                }
                byte[] src = Convert.FromBase64String(hashedPassword);
                if ((src.Length != 0x31) || (src[0] != 0))
                {
                    return PasswordVerificationResult.Failed;
                }
                byte[] dst = new byte[0x10];
                Buffer.BlockCopy(src, 1, dst, 0, 0x10);
                byte[] buffer3 = new byte[0x20];
                Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
                using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(providedPassword, dst, 0x3e8))
                {
                    buffer4 = bytes.GetBytes(0x20);
                }

                if (ByteEqual(buffer3, buffer4))
                {
                    return PasswordVerificationResult.Success;
                }
                else
                {
                    return PasswordVerificationResult.Failed;
                }
            }

            /// <summary>
            /// 比较两个字节数组
            /// </summary>
            /// <param name="b1"></param>
            /// <param name="b2"></param>
            /// <returns></returns>
            private static bool ByteEqual(byte[] b1, byte[] b2)
            {
                if (b1.Length != b2.Length) return false;
                if (b1 == null || b2 == null) return false;
                for (int i = 0; i < b1.Length; i++)
                {
                    if (b1[i] != b2[i])
                    {
                        return false;
                    }
                }
                return true;
            }
        }
    }
}
这两个类,为我们提供了用户认证常用的方法。接下来,你在创建UserManager类的时候,发现,需要提供Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>类型对象来构造UserManager对象,于是我继承了这个Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>接口:



using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
/******************************************************************************************************************
 * 
 * 
 * 说 明:TiKuUserStore (版本:Version1.0.0)
 * 作 者:李朝强
 * 日 期:2015/05/19
 * 修 改:
 * 参 考:http://my.oschina.net/lichaoqiang/
 * 备 注:暂无...
 * 
    IUserLockoutStore<User, TKey>: 在尝试一定的失败次数后允许锁定一个账号
    IUserEmailStore<User, TKey>: 使用邮件地址做确认 (例如通过邮件进行确认)
    IUserPhoneNumberStore<User, TKey>: 使用手机号码做确认(例如通过短信进行确认)
    IUserTwoFactorStore<User, TKey>: 启用2中途径进行安全验证 (例如通过用户名/密码和通过邮件或者短信的令牌),当用户密码可能存在不安全隐患的时候,系统会以短信或邮件的方式向用户发送安全码

 * 
 * ***************************************************************************************************************/
namespace AspNetIdentity.Models
{
    public class TiKuUserStore : Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>,
                                 IUserPasswordStore<TiKuUser, Guid>,
                                 IUserClaimStore<TiKuUser, Guid>,
                                 IUserLockoutStore<TiKuUser, Guid>,
                                 IUserEmailStore<TiKuUser, Guid>,
                                 IUserPhoneNumberStore<TiKuUser, Guid>,
                                 IUserTwoFactorStore<TiKuUser, Guid>
    {

        /// <summary>
        /// 声明
        /// </summary>
        public IList<System.Security.Claims.Claim> Claims = null;

        /// <summary>
        /// 实例化
        /// </summary>
        public TiKuUserStore()
        {
            //声明
            Claims = new List<System.Security.Claims.Claim>();
        }

        /// <summary>
        /// 用户
        /// </summary>
        public TiKuUser UserIdentity = null;


        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task CreateAsync(TiKuUser user)
        {
            return Task.Run(() =>
              {
                  string strInsertCmd = @"INSERT INTO[tb_User](ID,UserName,UserPwd) VALUES(@UserID,@UserName,@UserPwd);";
                  SqlParameter[] parameters = {
                                               new SqlParameter("@UserName",SqlDbType.NVarChar,30),
                                               new SqlParameter("@UserPwd",SqlDbType.NVarChar,100),
                                               new SqlParameter("@UserID",SqlDbType.UniqueIdentifier)
                                              };
                  parameters[0].Value = user.UserName;
                  parameters[1].Value = user.Password;
                  parameters[2].Value = user.Id;

                  int iResult = DbHelper.ExecuteNonQuery(strInsertCmd, parameters);
              });
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task DeleteAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 2>通过用户ID,获取用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task<TiKuUser> FindByIdAsync(Guid userId)
        {
            return Task<TiKuUser>.Run<TiKuUser>(() =>
            {
                if (UserIdentity != null) { return UserIdentity; }

                string strCmd = "SELECT * FROM [tb_User] WHERE ID=@UserID;";
                SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.UniqueIdentifier) };
                parameters[0].Value = userId;
                List<TiKuUser> list = new List<TiKuUser>();
                using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters))
                {
                    while (data.Read())
                    {
                        //model
                        TiKuUser user = new TiKuUser();
                        user.Id = Guid.Parse(data["ID"].ToString());
                        user.UserName = data["UserName"].ToString();
                        user.Password = data["UserPwd"].ToString();

                        list.Add(user);
                    }
                }
                UserIdentity = list.FirstOrDefault();
                return UserIdentity;
            });
        }

        /// <summary>
        /// 1>通过用户名获取用户信息
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task<TiKuUser> FindByNameAsync(string userName)
        {
            return Task<TiKuUser>.Run<TiKuUser>(() =>
            {
                if (UserIdentity != null) { return UserIdentity; }

                string strCmd = "SELECT * FROM [tb_User] WHERE UserName=@UserName;";
                SqlParameter[] parameters = { new SqlParameter("@UserName", SqlDbType.NVarChar, 30) };
                parameters[0].Value = userName;
                List<TiKuUser> list = new List<TiKuUser>();
                using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters))
                {

                    while (data.Read())
                    {
                        //model
                        TiKuUser user = new TiKuUser();
                        user.Id = Guid.Parse(data["ID"].ToString());
                        user.UserName = data["UserName"].ToString();
                        user.Password = data["UserPwd"].ToString();
                        list.Add(user);
                    }
                }

                //模拟数据库
                UserIdentity = list.FirstOrDefault();

                return UserIdentity;
            });
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task UpdateAsync(TiKuUser user)
        {
            return Task.Run(() =>
            {

            });
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取密码
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetPasswordHashAsync(TiKuUser user)
        {
            return Task<string>.Run(() =>
            {
                return user.Password;
            });
        }

        /// <summary>
        /// 是否有密码
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> HasPasswordAsync(TiKuUser user)
        {
            return Task.FromResult<bool>(!string.IsNullOrEmpty(user.Password));
        }

        /// <summary>
        /// 密码进行加密
        /// </summary>
        /// <param name="user"></param>
        /// <param name="passwordHash"></param>
        /// <returns></returns>
        public Task SetPasswordHashAsync(TiKuUser user, string passwordHash)
        {
            return Task.Run(() =>
            {
                user.Password = passwordHash;//加密后
            });
        }


        /// <summary>
        /// 添加一个声明
        /// </summary>
        /// <param name="user"></param>
        /// <param name="claim"></param>
        /// <returns></returns>
        public Task AddClaimAsync(TiKuUser user, System.Security.Claims.Claim claim)
        {
            return Task.Run(() => { Claims.Add(claim); });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<IList<System.Security.Claims.Claim>> GetClaimsAsync(TiKuUser user)
        {
            return Task.Run<IList<System.Security.Claims.Claim>>(() =>
            {
                IList<System.Security.Claims.Claim> list = new List<System.Security.Claims.Claim>();

                //声明
                //System.Security.Claims.Claim claimUserName = new System.Security.Claims.Claim("nick", user.UserName);//UserName
                //System.Security.Claims.Claim claimUserId = new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, user.Id.ToString());//UserId
                //list.Add(claimUserName);
                //list.Add(claimUserId);

                return list;
            });
        }

        /// <summary>
        /// 移除声明
        /// </summary>
        /// <param name="user"></param>
        /// <param name="claim"></param>
        /// <returns></returns>
        public Task RemoveClaimAsync(TiKuUser user, System.Security.Claims.Claim claim)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取访问失败次数
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<int> GetAccessFailedCountAsync(TiKuUser user)
        {
            return Task<Int32>.FromResult<Int32>(1);
        }

        /// <summary>
        /// 获取锁定状态
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetLockoutEnabledAsync(TiKuUser user)
        {
            return Task<bool>.Run<bool>(() =>
            {
                return false;
            });
        }

        /// <summary>
        /// 获取锁定结束时间
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<DateTimeOffset> GetLockoutEndDateAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<int> IncrementAccessFailedCountAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 重置访问时间计数
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task ResetAccessFailedCountAsync(TiKuUser user)
        {
            return Task.FromResult(false);
        }

        #region  LockOut
        /// <summary>
        /// 修改锁定状态
        /// </summary>
        /// <param name="user"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public Task SetLockoutEnabledAsync(TiKuUser user, bool enabled)
        {
            return Task.Run(() =>
            {

            });
        }

        /// <summary>
        /// 设置锁定时间
        /// </summary>
        /// <param name="user"></param>
        /// <param name="lockoutEnd"></param>
        /// <returns></returns>
        public Task SetLockoutEndDateAsync(TiKuUser user, DateTimeOffset lockoutEnd)
        {
            return Task.Run(() =>
            {

            });
        }
        #endregion

        #region Email

        /// <summary>
        /// 通过邮箱获取用户信息
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public Task<TiKuUser> FindByEmailAsync(string email)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取用户邮箱
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetEmailAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 确认邮件
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetEmailConfirmedAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 修改邮箱
        /// </summary>
        /// <param name="user"></param>
        /// <param name="email"></param>
        /// <returns></returns>
        public Task SetEmailAsync(TiKuUser user, string email)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="confirmed"></param>
        /// <returns></returns>
        public Task SetEmailConfirmedAsync(TiKuUser user, bool confirmed)
        {
            throw new NotImplementedException();
        }


        #endregion

        #region Phone

        /// <summary>
        /// 获取手机号
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetPhoneNumberAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetPhoneNumberConfirmedAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public Task SetPhoneNumberAsync(TiKuUser user, string phoneNumber)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="confirmed"></param>
        /// <returns></returns>
        public Task SetPhoneNumberConfirmedAsync(TiKuUser user, bool confirmed)
        {
            throw new NotImplementedException();
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetTwoFactorEnabledAsync(TiKuUser user)
        {
            return Task.Run<bool>(() =>
              {
                  return false;
              });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public Task SetTwoFactorEnabledAsync(TiKuUser user, bool enabled)
        {
            return Task.Run(() =>
            {

            });
        }
    }
}
下面,我们看看注册方法该怎么写,在这里,我用MVC5作为代码示例,在解决方案中,创建AccountController控制器:
[Authorize]
    public class AccountController : Controller
    {

        /// <summary>
        ///注册:这里省事,没有写UI
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AllowAnonymous]
        public async Task<ActionResult> Register()
        {

            //user
            TiKuUser user = new TiKuUser { Id = Guid.NewGuid(), UserName = "chaoqiangli", Password = "XXXX" };

            //Context
            Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext();

            //用户储存
            Models.TiKuUserStore userStore = new Models.TiKuUserStore();

            //UserManager
            TiKuUserManager UserManager = new TiKuUserManager(userStore);

            IdentityResult result = await UserManager.CreateAsync(user, user.Password);
            if (result.Succeeded)
            {
                Response.Write("注册成功!");
            }
            return View();
        }
}




我们来看看,Models.TiKuUserStore 对象都完成了那些工作。


using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
/******************************************************************************************************************
 * 
 * 
 * 说 明:TiKuUserStore (版本:Version1.0.0)
 * 作 者:李朝强
 * 日 期:2015/05/19
 * 修 改:
 * 参 考:http://my.oschina.net/lichaoqiang/
 * 备 注:暂无...
 * 
    IUserLockoutStore<User, TKey>: 在尝试一定的失败次数后允许锁定一个账号
    IUserEmailStore<User, TKey>: 使用邮件地址做确认 (例如通过邮件进行确认)
    IUserPhoneNumberStore<User, TKey>: 使用手机号码做确认(例如通过短信进行确认)
    IUserTwoFactorStore<User, TKey>: 启用2中途径进行安全验证 (例如通过用户名/密码和通过邮件或者短信的令牌),当用户密码可能存在不安全隐患的时候,系统会以短信或邮件的方式向用户发送安全码

 * 
 * ***************************************************************************************************************/
namespace AspNetIdentity.Models
{
    public class TiKuUserStore : Microsoft.AspNet.Identity.IUserStore<TiKuUser, Guid>,
                                 IUserPasswordStore<TiKuUser, Guid>,
                                 IUserClaimStore<TiKuUser, Guid>,
                                 IUserLockoutStore<TiKuUser, Guid>,
                                 IUserEmailStore<TiKuUser, Guid>,
                                 IUserPhoneNumberStore<TiKuUser, Guid>,
                                 IUserTwoFactorStore<TiKuUser, Guid>
    {

        /// <summary>
        /// 声明
        /// </summary>
        public IList<System.Security.Claims.Claim> Claims = null;

        /// <summary>
        /// 实例化
        /// </summary>
        public TiKuUserStore()
        {
            //声明
            Claims = new List<System.Security.Claims.Claim>();
        }

        /// <summary>
        /// 用户
        /// </summary>
        public TiKuUser UserIdentity = null;


        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task CreateAsync(TiKuUser user)
        {
            return Task.Run(() =>
              {
                  string strInsertCmd = @"INSERT INTO[tb_User](ID,UserName,UserPwd) VALUES(@UserID,@UserName,@UserPwd);";
                  SqlParameter[] parameters = {
                                               new SqlParameter("@UserName",SqlDbType.NVarChar,30),
                                               new SqlParameter("@UserPwd",SqlDbType.NVarChar,100),
                                               new SqlParameter("@UserID",SqlDbType.UniqueIdentifier)
                                              };
                  parameters[0].Value = user.UserName;
                  parameters[1].Value = user.Password;
                  parameters[2].Value = user.Id;

                  int iResult = DbHelper.ExecuteNonQuery(strInsertCmd, parameters);
              });
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task DeleteAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 2>通过用户ID,获取用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task<TiKuUser> FindByIdAsync(Guid userId)
        {
            return Task<TiKuUser>.Run<TiKuUser>(() =>
            {
                if (UserIdentity != null) { return UserIdentity; }

                string strCmd = "SELECT * FROM [tb_User] WHERE ID=@UserID;";
                SqlParameter[] parameters = { new SqlParameter("@UserID", SqlDbType.UniqueIdentifier) };
                parameters[0].Value = userId;
                List<TiKuUser> list = new List<TiKuUser>();
                using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters))
                {
                    while (data.Read())
                    {
                        //model
                        TiKuUser user = new TiKuUser();
                        user.Id = Guid.Parse(data["ID"].ToString());
                        user.UserName = data["UserName"].ToString();
                        user.Password = data["UserPwd"].ToString();

                        list.Add(user);
                    }
                }
                UserIdentity = list.FirstOrDefault();
                return UserIdentity;
            });
        }

        /// <summary>
        /// 1>通过用户名获取用户信息
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task<TiKuUser> FindByNameAsync(string userName)
        {
            return Task<TiKuUser>.Run<TiKuUser>(() =>
            {
                if (UserIdentity != null) { return UserIdentity; }

                string strCmd = "SELECT * FROM [tb_User] WHERE UserName=@UserName;";
                SqlParameter[] parameters = { new SqlParameter("@UserName", SqlDbType.NVarChar, 30) };
                parameters[0].Value = userName;
                List<TiKuUser> list = new List<TiKuUser>();
                using (IDataReader data = DbHelper.ExecuteReader(strCmd, parameters))
                {

                    while (data.Read())
                    {
                        //model
                        TiKuUser user = new TiKuUser();
                        user.Id = Guid.Parse(data["ID"].ToString());
                        user.UserName = data["UserName"].ToString();
                        user.Password = data["UserPwd"].ToString();
                        list.Add(user);
                    }
                }

                //模拟数据库
                UserIdentity = list.FirstOrDefault();

                return UserIdentity;
            });
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public System.Threading.Tasks.Task UpdateAsync(TiKuUser user)
        {
            return Task.Run(() =>
            {

            });
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取密码
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetPasswordHashAsync(TiKuUser user)
        {
            return Task<string>.Run(() =>
            {
                return user.Password;
            });
        }

        /// <summary>
        /// 是否有密码
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> HasPasswordAsync(TiKuUser user)
        {
            return Task.FromResult<bool>(!string.IsNullOrEmpty(user.Password));
        }

        /// <summary>
        /// 密码进行加密
        /// </summary>
        /// <param name="user"></param>
        /// <param name="passwordHash"></param>
        /// <returns></returns>
        public Task SetPasswordHashAsync(TiKuUser user, string passwordHash)
        {
            return Task.Run(() =>
            {
                user.Password = passwordHash;//加密后
            });
        }


        /// <summary>
        /// 添加一个声明
        /// </summary>
        /// <param name="user"></param>
        /// <param name="claim"></param>
        /// <returns></returns>
        public Task AddClaimAsync(TiKuUser user, System.Security.Claims.Claim claim)
        {
            return Task.Run(() => { Claims.Add(claim); });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<IList<System.Security.Claims.Claim>> GetClaimsAsync(TiKuUser user)
        {
            return Task.Run<IList<System.Security.Claims.Claim>>(() =>
            {
                IList<System.Security.Claims.Claim> list = new List<System.Security.Claims.Claim>();

                //声明
                //System.Security.Claims.Claim claimUserName = new System.Security.Claims.Claim("nick", user.UserName);//UserName
                //System.Security.Claims.Claim claimUserId = new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, user.Id.ToString());//UserId
                //list.Add(claimUserName);
                //list.Add(claimUserId);

                return list;
            });
        }

        /// <summary>
        /// 移除声明
        /// </summary>
        /// <param name="user"></param>
        /// <param name="claim"></param>
        /// <returns></returns>
        public Task RemoveClaimAsync(TiKuUser user, System.Security.Claims.Claim claim)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取访问失败次数
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<int> GetAccessFailedCountAsync(TiKuUser user)
        {
            return Task<Int32>.FromResult<Int32>(1);
        }

        /// <summary>
        /// 获取锁定状态
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetLockoutEnabledAsync(TiKuUser user)
        {
            return Task<bool>.Run<bool>(() =>
            {
                return false;
            });
        }

        /// <summary>
        /// 获取锁定结束时间
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<DateTimeOffset> GetLockoutEndDateAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<int> IncrementAccessFailedCountAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 重置访问时间计数
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task ResetAccessFailedCountAsync(TiKuUser user)
        {
            return Task.FromResult(false);
        }

        #region  LockOut
        /// <summary>
        /// 修改锁定状态
        /// </summary>
        /// <param name="user"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public Task SetLockoutEnabledAsync(TiKuUser user, bool enabled)
        {
            return Task.Run(() =>
            {

            });
        }

        /// <summary>
        /// 设置锁定时间
        /// </summary>
        /// <param name="user"></param>
        /// <param name="lockoutEnd"></param>
        /// <returns></returns>
        public Task SetLockoutEndDateAsync(TiKuUser user, DateTimeOffset lockoutEnd)
        {
            return Task.Run(() =>
            {

            });
        }
        #endregion

        #region Email

        /// <summary>
        /// 通过邮箱获取用户信息
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public Task<TiKuUser> FindByEmailAsync(string email)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取用户邮箱
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetEmailAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 确认邮件
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetEmailConfirmedAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 修改邮箱
        /// </summary>
        /// <param name="user"></param>
        /// <param name="email"></param>
        /// <returns></returns>
        public Task SetEmailAsync(TiKuUser user, string email)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="confirmed"></param>
        /// <returns></returns>
        public Task SetEmailConfirmedAsync(TiKuUser user, bool confirmed)
        {
            throw new NotImplementedException();
        }


        #endregion

        #region Phone

        /// <summary>
        /// 获取手机号
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<string> GetPhoneNumberAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetPhoneNumberConfirmedAsync(TiKuUser user)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public Task SetPhoneNumberAsync(TiKuUser user, string phoneNumber)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="confirmed"></param>
        /// <returns></returns>
        public Task SetPhoneNumberConfirmedAsync(TiKuUser user, bool confirmed)
        {
            throw new NotImplementedException();
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Task<bool> GetTwoFactorEnabledAsync(TiKuUser user)
        {
            return Task.Run<bool>(() =>
              {
                  return false;
              });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public Task SetTwoFactorEnabledAsync(TiKuUser user, bool enabled)
        {
            return Task.Run(() =>
            {

            });
        }
    }
}
现在,我们可以编写用户注册的方法了,这是,我们会用到另一个对象,TiKuUser,它继承自Microsoft.AspNet.Identity.IUser<Guid>接口,根据实际情况,我们可以去拓展它。



using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;

namespace AspNetIdentity.Models
{
    public class TiKuUser : Microsoft.AspNet.Identity.IUser<Guid>
    {
        /// <summary>
        /// 用户编号
        /// </summary>
        public Guid Id
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        [DisplayName("登录名")]
        public string UserName
        {
            get;
            set;
        }

        /// <summary>
        /// 密码
        /// </summary>
        [DisplayName("密码")]
        public string Password { get; set; }

        /// <summary>
        /// 昵称
        /// </summary>
        [DisplayName("昵称")]
        public string Nick { get; set; }


    }
}
这样,就完成了用户的注册。接下来,就是用户认证的过程了。这时,你会发现,Microsoft.AspNet.Identity.Owin.SignInManager为我们提供了丰富的方法,来完成用户的认证。认证成功后,会向客户端发送加密的Cookie。这时,我们可通过HttpContext.Current.User对象,来获取认证信息。


登录代码如下:


/// <summary>
        /// 登陆
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<ActionResult> Login(TiKuUser @user)
        {

            if (string.IsNullOrEmpty(@user.UserName)) { return View(); }
            if (string.IsNullOrEmpty(@user.Password)) { return View(); }

            //Context
            Microsoft.Owin.IOwinContext OwinContext = HttpContext.GetOwinContext();

            //实例化UserStore对象
            Models.TiKuUserStore userStore = new Models.TiKuUserStore();

            //UserManager
            TiKuUserManager UserManager = new TiKuUserManager(userStore);

            //signInManager
            TiKuSignInManager signInManager = new TiKuSignInManager(UserManager, AutherticationManager);


            //登录
            Microsoft.AspNet.Identity.Owin.SignInStatus SignInStatus = await signInManager.PasswordSignInAsync(@user.UserName,
                                                                                                               @user.Password,
                                                                                                               true,
                                                                                                               shouldLockout: false);

            //状态
            switch (SignInStatus)
            {
                //成功
                case Microsoft.AspNet.Identity.Owin.SignInStatus.Success:

                    //标示
                    //System.Security.Claims.ClaimsIdentity identity = UserManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);

                    //授权登陆
                    //AutherticationManager.SignIn(new Microsoft.Owin.Security.AuthenticationProperties { IsPersistent = true }, identity);
                    return RedirectToAction("index", "home");
                //锁定
                case Microsoft.AspNet.Identity.Owin.SignInStatus.LockedOut:
                    Response.Write("LockedOut!");
                    break;
                //要求验证
                case Microsoft.AspNet.Identity.Owin.SignInStatus.RequiresVerification:
                    Response.Write("RequiresVerification!");
                    break;
                //登录失败
                case Microsoft.AspNet.Identity.Owin.SignInStatus.Failure:
                    Response.Write("Failure!");
                    break;

            }

            return View(@user);
        }
    }
我们来看看实际效果吧。


这里,做了个简单的登录表单。登录成功后,会发现,客户端多了一长串Cookie。

这是加密后的用户登录凭据。这样,用户认证成功后,就可以访问到[Authorize]的Action了。

    我们在创建MVC项目的时候,有两个文件需要注意下,就是根目录下的Startup.cs和App_Start目录下的Startup.Auth.cs两个类,它们以分布类的形式,存放于解决方案不同目录中。我们看看Startup都做了那些工作。


using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
/******************************************************************************************************************
 * 
 * 
 * 说 明: Startup(版本:Version1.0.0)
 * 作 者:李朝强
 * 日 期:2015/05/19
 * 修 改:
 * 参 考:http://my.oschina.net/lichaoqiang/
 * 备 注:暂无...
 * 
 * 
 * ***************************************************************************************************************/
[assembly: OwinStartup(typeof(AspNetIdentity.Startup))]
namespace AspNetIdentity
{
    public partial class Startup
    {
        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="app"></param>
        public void Configuration(IAppBuilder app)
        {
            // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
            ConfigureAuth(app);
        }
    }
}

using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AspNetIdentity
{
    public partial class Startup
    {
        // 有关配置身份验证的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {

            // 使应用程序可以使用 Cookie 来存储已登录用户的信息
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                CookieHttpOnly = true,
                CookieName = "__KaoLaTicketSid"
            });

            // Use a cookie to temporarily store information about a user logging in with a third party login provider
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        }
    }
}

有了这个两个启动类,应用程序在启动的时候,就会触发Configuration方法,完成OWIN的配置工作。

 如果你有更多疑问,不妨说出来,我们共同探讨。



© 著作权归作者所有

共有 人打赏支持
李朝强
粉丝 80
博文 268
码字总数 137210
作品 0
郑州
产品经理
加载中

评论(6)

科-刘
科-刘
正需要这个
c
chanz
有完整示例下载吗?
我是奥奥
请大神收下在下 菜鸟一枚 愿追随左右
卖套的程序猿
卖套的程序猿
少些了一句 IAuthenticationManager AutherticationManager=OwinContext .Authentication;
jamesvon
jamesvon
在口令验证过程中,SignInManager的PasswordSignInAsync里面你直接调用了基类函数,然后调用UserManager中的OldSystemPasswordHasher中的VerifyHashedPassword完成检验,可VerifyHashedPassword返回的是PasswordVerificationResult类型,而PasswordSignInAsync返回的则是SignInStatus类型,两者是如何转换的?如果VerifyHashedPassword返回PasswordVerificationResult.SuccessRehashNeeded系统就会异常!不知道如何处理
夏至如沫
夏至如沫
赞一个
关于您重写的c# identity 登录识别锁定实现

@李朝强 您好,想跟您请教个问题: public Task IncrementAccessFailedCountAsync(TiKuUser user) { throw new NotImplementedException(); } 拜读您的文章 ”OWIN+AspNet.Identity完成用户注......

fage008 ⋅ 2017/03/23 ⋅ 0

建立自己的 MVC portal (一)

目标和任务 建立一个以.net MVC架构为基础的,采用OWIN+AspNet.Identity认证体系的,支持多站点的Portal平台,主要包含平台基本功能和一个新闻模块。 建立一个具有良好扩展功能和研发扩展需求...

jamesvon ⋅ 2016/05/04 ⋅ 0

Window上python开发--4.Django的用户登录模块User

在搭建网站和web的应用程序时,用户的登录和管理是几乎是每个网站都必备的。今天主要从一个实例了解以下django本身自带的user模块。本文并不对user进行扩展。 主要使用原生的模块。 1.User模...

jackxu2015 ⋅ 2015/08/14 ⋅ 0

统一认证,移动互联网时代应用开发未来的最佳登录注册方式?

统一认证:移动互联网时代的用户账号一站式管理平台 随着智能手机已经完全普及化,移动互联网时×××始真正的到来,随之而来的也是庞大的应用开发市场。 1. 应用(APP)登录 移动互联网时代...

505647699 ⋅ 04/27 ⋅ 0

Spring Security教程

Spring Security是一个灵活和强大的身份验证和访问控制框架,以确保基于Spring的Java Web应用程序的安全。 在这些简单Spring Security4 一系列教程中的 Spring Security 示例是基于新的Sprin...

易百教程 ⋅ 2016/08/30 ⋅ 1

跌倒了,再爬起来:ASP.NET 5 Identity

“跌倒了”指的是这一篇博文:爱与恨的抉择:ASP.NET 5+EntityFramework 7 如果想了解 ASP.NET Identity 的“历史”及“原理”,强烈建议读一下这篇博文:MVC5 - ASP.NET Identity登录原理 ...

林羽恒 ⋅ 2017/06/19 ⋅ 0

ASP.NET MVC中三方登录: 微软、谷歌、Office365

创建一个MVC的工程,在Startup.Auth.cs文件中,我们能看到这样的一些代码: 这其实是微软已经帮我们实现好的三方登录的接口,我们只需要创建相应的开发者账号,并在其中配置好跟我们应用程序...

葡萄城控件技术团队 ⋅ 2015/05/19 ⋅ 0

单点登录原理与简单实现

一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关联,这个过...

余平的余_余平的平 ⋅ 2017/11/03 ⋅ 0

单点登录原理与简单实现

一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关联,这个过...

skymyyang ⋅ 2016/12/19 ⋅ 0

Shiro和Spring Security对比

Shiro简介 Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大,但是在实际工作时可能并不...

有余力则学文 ⋅ 04/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 52分钟前 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 1

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

CentOS开机启动subversion

建立自启动脚本: vim /etc/init.d/subversion 输入如下内容: #!/bin/bash## subversion startup script for the server## chkconfig: 2345 90 10# description: start the subve......

随风而飘 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部