本文不讲原理,只讲用法,原理性的东西网上特别多,不过还是会对一些要用到的东西进行解释,不深入讲原理。本文中用的是Vs2012   .net mvc 4.0。原理看这篇文章,看完这个文章绝对受益匪浅。

说下登录的整个流程:用户输入账号密码->点击提交->数据提交到后台控制器->去数据库取得用户资料->如果登录成功->将数据写入cookie(也就是写入forms身份验证)->返回给控制器登录状态->对相应的登录状态进行处理。

第一步:新建一个.net mvc 4.0的解决方案,然后配置 WebConfig文件

在 <system.web>节点下添加以下代码:

    <authentication mode="Forms" name="CookieName">
<forms loginUrl="~/Login/Login" timeout="" />
</authentication>

简要说明 一下上面的代码:

  loginUrl登录页的URL。通过FormsAuthentication.LoginUrl属性可以得到该配置值。当调用FormsAuthentication.RedirectToLoginPage()方法时,客户端请求将被重定向到该属性所指定的页面。如果没有设置这个属性,.net也会尝试在目录下寻找名为login.aspx的文件;

  mode属性,就是选择的是Forms模式的登录,还有其他模式(Windows,Passport等等);

  name属性,是cookie的名称,在获取登录的cookie时需要通过这个name来取得登陆用的Cookie;

  timeout属性,就是Cookie的过期时间,可以同slidingExpiration属性 配合使用;

  slidingExpiration属性,是否启用“弹性过期时间”,如果该属性设置为false,从首次验证之后过timeout时间后Cookie即过期;如果该属性为true,则从上次请求该开始过timeout时间才过期,也就是说,如果在timeout时间内,再次向服务器端发送请求,则Cookie将永远不会过期。

以上是主要用到的一些属性。

关于配置文件,若有数据库,当然还要配置数据库连接,这里就不多说了。

第二步:创建用户类型:UserModel

  这个类主要是用来保存登录的用户的对象。

    /// <summary>使用者</summary>
public class UserModels
{
/// <summary>使用者编号</summary>
[Display(Name = "使用者编号")]
public int users_db_id { get; set; } /// <summary>用戶姓名</summary>
[Display(Name = "用户姓名")]
public string users_name { get; set; } /// <summary>账号</summary>
[Display(Name = "账号")]
public string login_id { get; set; } /// <summary>密码</summary>
[Display(Name = "密码")]
public string login_pwd { get; set; } /// <summary>身分</summary>
[Display(Name = "身份")]
public int users_position { get; set; }
}

在这里不对角色做太多的处理,users_position简要的表明用户所属的角色。

第三步:添加一个生产身份验证的类SetCookies

public class SetCookies
{
public static void SetCookie(string id, bool chkAutoLogin, int role)
{
DateTime EndDate = DateTime.Now;
if (chkAutoLogin)
{
EndDate = DateTime.Now.AddDays();
} string Role = string.Empty; switch (role)//这里简要这几个角色,实际应用中可以从数据库中读取角色
{
case :
Role = "Agent";//客户
break;
case :
Role = "Business";//供应商
break;
case :
Role = "Financial";//财务
break;
case :
Role = "Boss";//老板
break;
} //生产身份验证
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(,id,DateTime.Now,EndDate,true,Role,FormsAuthentication.FormsCookiePath); //对身份验证的标识进行加密
string encTicket = FormsAuthentication.Encrypt(ticket); //创建将要写入到客户端的Cookie
HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, id);
       //如果勾选了是否自动登录,则将过期时间推迟14天
if (chkAutoLogin)
{
newCookie.Expires = EndDate;
}
//写入到客户端
HttpContext.Current.Request.Cookies.Add(newCookie);
}
}
FormsAuthentication.FormsCookieName 就是刚才在配置文件中的name属性的值
这里小写的role 类似于数据库用户表的外键(一般都有一个权限表,这里假设只有用户表和角色表),大写的Role类似于数据库角色表的角色名称,这里简要处理角色,所以在真正项目中,可以在这里从数据库读取用户的角色,然后将其角色用逗号(或者其他符号隔开),生产一个角色字符串(类似于Role="角色A,角色B,角色C")。最后将这个Role传到FormsAuthenticationTicket 类的UserData参数中,在后面判断角色的时候用到,UserData这个参数也不一定要放角色,也可以放其他要用到的数据,因项目而异。对FormsAuthenticationTicket 这个类不清楚的,可以自己看看定义(最好还是去看看,对理解这个Forms验证登录有帮助)。以上这个类也算是Forms登录中最重要的一步了。
第三步:验证登录,从数据库拿数据,然后返回登录状态
先给出登录状态的类,这是一个枚举类型
    public class EnumList
{
public enum LoginSts
{
/// <summary>登入成功</summary>
Sucess,
/// <summary>密碼錯誤</summary>
PasswordError,
/// <summary>帳號不存在</summary>
NoExists,
/// <summary>登入失敗</summary>
LoginError
}
}

这个是枚举类型,不做解释。

 public class SetLoginRepository
{
public static Tuple<EnumList.LoginSts, int> SetLogin(string id, string pwd = "", bool IsAutoLogin = false)
{
       //关于以下这种类型的用法,请看另一篇文章,或者网上搜索Tuple,没有这个类型对本文章没有多大的影响,因为这个类型就是用来返回 多种数据类型 的数据 的类型
Tuple<EnumList.LoginSts, int> status = new Tuple<EnumList.LoginSts, int>(EnumList.LoginSts.LoginError, );
UserModels userData = GetUserData(id);//取得用户数据
if (userData != null)
{
if (string.IsNullOrWhiteSpace(pwd) || userData.login_pwd == pwd)
{
//你可以在这里将登录的用户对象存放到Session中,以便将来要用到这个对象,比如Session["Account"]=userData
SetCookies.SetCookie(id, IsAutoLogin, userData.users_position);//这里就是调用上面的那个写入身份验证的方法
status = new Tuple<EnumList.LoginSts, int>(EnumList.LoginSts.Sucess, userData.users_position);
}
else
{
status = new Tuple<EnumList.LoginSts, int>(EnumList.LoginSts.PasswordError, );
}
}
else
{
status = new Tuple<EnumList.LoginSts, int>(EnumList.LoginSts.NoExists, );
}
return status;
}
    //从数据库取得用户数据,这里使用的是Ado.net
public static UserModels GetUserData(string id)
{
UserModels model = new UserModels();
string connStr = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select top 1 * from users_db where login_id='" + id + "' and datastatus=1 "; SqlDataReader sdr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow);
if (sdr.Read())
{
model.users_db_id = Convert.ToInt32(sdr["users_db_id"]);
model.login_id = sdr["login_id"].ToString();
model.users_name = sdr["users_name"].ToString();
model.login_pwd = sdr["login_pwd"].ToString();
model.datastatus = Convert.ToBoolean(sdr["datastatus"].ToString());
model.users_position = Convert.ToInt32(sdr["users_position"]);
}
}
return model;
}
}

关于Tuple<T1,T2...T8> 的用法请看另一篇文章.Net 4.0特性 Tuple元组

。这里先简要解释一下它的作用,Tuple就是可以自定义任何类型,在返回值的时候,可以返回任意多个类型的数据,我认为它的作用就是能返回多种类型的数据。然后可以通过该类型的实例获得相应的值,获取值的方法是比如这个类的实例叫tuple,则取得值的方法是tuple.Item1,tuple.Item2....tuple.Item8,通过这个可以取得对应位置的值。这就很方便的给我们提供了可以在一个方法里面返回多种数据类型。

第四步:也是非常重要的一步,Global文件添加一个方法:

        //取得自定义的角色
public void Application_AuthenticateRequest(object sender, EventArgs e) {
if (Request.IsAuthenticated) {
// 先取得该使用者的 FormsIdentity
FormsIdentity id = (FormsIdentity)User.Identity;
// 再取出使用者的 FormsAuthenticationTicket
FormsAuthenticationTicket ticket = id.Ticket;
// 將储存在 FormsAuthenticationTicket 中的角色定义取出,并转成字符串数组
string[] roles = ticket.UserData.Split(new char[] { ',' });
// 指派角色到目前这个 HttpContext 的 User 物件去
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}

这个方法是在Global文件中定义的,在客户端每次发一个请求都会先经过这个方法,即使是Ajax请求也同样要先经过这个方法。注释写得很清楚,不多说。

第五步 :写控制器LoginController

        public ActionResult SetLogin(string Name, string Password)
{
if (ModelState.IsValid)
{
Tuple<EnumList.LoginSts, int> status = SetLoginRepository.SetLogin(Name, Password, true);
switch (status.Item1)//这个.Item1就是Tuple类型取得对应位置类型 的值 的方法
{
case EnumList.LoginSts.Sucess:
if (status.Item2 == )
{
//对登录成功的情况进行处理,可以跳转到列表页或者网站首页之类的
return RedirectToAction("actionName","ControlName");
}
break;
case EnumList.LoginSts.NoExists:
//对用户不存在的情况进行处理
break;
case EnumList.LoginSts.PasswordError:
//对密码错误的情况进行处理
break;
}
}
return View();
}

顺便附上退出的代码:

        public static void ClearSessionAndCookie()
{
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
cookie.Expires.AddDays(-);
HttpContext.Current.Response.Cookies.Add(cookie);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Session.Abandon();
FormsAuthentication.SignOut();
}

代码很简单,就是清除Cookie,清除Cookie的方法就是将它的过期时间设置为前一天。然后FormsAuthentication.SignOut()就退出了。

整个流程完成,前台页面的代码就不写了,就两个文本框加上一个登录按钮。还有一个是否自动登录的按钮,这里就不演示了。

一步一步实现FormsAuthentic验证登录的更多相关文章

  1. 一步一步来做WebQQ机器人-(三)(登录QQ并保持在线)

    × 本篇的目的是让你的QQ真正的上线:挤下你的PCQQ,和让好友状态栏显示webqq在线 目前总进度大概50% 全系列预计会有这些步骤,当然某些步骤可能会合并: 验证码 第一次登陆 第二次登陆 保持在 ...

  2. 一步一步从原理跟我学邮件收取及发送 2.邮箱的登录和绕不开的base64

    一步一步从原理跟我学邮件收取及发送 2.邮箱的登录和绕不开的base64 好了,经过本系列上一篇文章 "1.网络命令的发送",假设大家已经掌握了 email 电子邮件的命令发送的方 ...

  3. xilinx IP核配置,一步一步验证Xilinx Serdes GTX最高8.0Gbps

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010161493/article/details/77658599   目录(?)[+]   之前 ...

  4. xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 2.登录的实现

    第二章登录的实现 金庸<倚天屠龙记> 张三丰缓缓摇头,说道:“少林派累积千年,方得达成这等绝技,决非一蹴而至,就算是绝顶聪明之人,也无法自创.”他顿了一顿,又道:“我当年在少林寺中住过,只 ...

  5. 一步一步来做WebQQ机器人-(二)(第一次登陆)

    // 预计会有这些步骤,当然某些步骤可能会合并: 验证码 第一次登陆 第二次登陆 保持在线和接收消息 获取好友和群列表 发送消息 变成智能的(*゚∀゚*) webqq的登陆,分为2步,本文主要讲第一次 ...

  6. 一步一步实现MVC5+EF6+Bootstarp+Autofac+NoSql实现OADemo 之登陆(一) 验证码 Captcha 之大插件小用

    不知何年何月才能完成OADemo啊,总之还是一步一步来吧,这段时间开始着手了,先做登陆.  前段时间研究了一下在CentOS7下安装Mysql和Memcached服务,并测试了用C#操作,结果还行. ...

  7. 一步一步教你将普通的wifi路由器变为智能广告路由器

    一步一步教你将普通的wifi路由器变为智能广告路由器 相信大家对WiFi智能广告路由器已经不再陌生了,现在很多公共WiFi上网,都需要登录并且验证,这也就是WiFi广告路由器的最重要的功能.大致就是下 ...

  8. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)

    前言 Hi, 大家好,还是星期五,还是Rector,又在图享网准时和大家见面了. 今天给大家带来系列教程<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Auto ...

  9. jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、

    脚 本 之 家 www.jb51.net 脚本云 专题 素材下载 电子书 软件下载 源码下载 服务器常用软件 a5交易 首页 网页制作 脚本专栏 脚本下载 网络编程 数据库 CMS教程 电子书籍 平面 ...

随机推荐

  1. javascript面向对象创建高级 Web 应用程序

       目录 JavaScript 对象是词典 JavaScript 函数是最棒的 构造函数而不是类 原型 静态属性和方法 闭包 模拟私有属性 从类继承 模拟命名空间 应当这样编写 JavaScript ...

  2. a='1,2,3,4,5'如何转换为['1','2','3','4','5']

    a='1,2,3,4,5'如何转换为['1','2','3','4','5'] b=a.split(',') split函数自动将分隔后的元素以逗号为分隔符存放到列表中 用处:有时需要用户输入多个数字 ...

  3. JVM 重排序

    在java代码到最终执行的指令序列的整个过程中,会出现重排序.也就是说最终执行的顺序并不是按照源代码执行的顺序来进行的. 其中1为编译器的优化重排序,2,3是处理器的重排序. 数据依赖 如果两个操作访 ...

  4. C语言深度剖析---预处理(define)(转载)

    1.数值宏常量     #define宏定义是个演技非常高超的替身演员,但也会耍大牌的,所以我们使用它要慎之又慎.它可以出现在代码的任何地方,从本行宏定义开始,以后的代码都认识宏了:也可以把任何东西都 ...

  5. USACO Healthy Holsteins DFS

    使用排列组合,遍历所有可能的情况C(1)+C(2)+C(3)……C(n)= 2^G种组合 数据规模不大,暴力过去最多也就是2^15 = 23768种情况 所以就暴力咯,不过还是Debug了一会 Sou ...

  6. Spring+EhCache缓存实例(详细讲解+源码下载)(转)

    一.ehcahe的介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider.Ehcache是一种广泛使用的开源Java分布式 ...

  7. 凡客副总裁被曝离职:或因IPO受阻|凡客|王春焕|离职_互联网_新浪科技_新浪网

    凡客副总裁被曝离职:或因IPO受阻|凡客|王春焕|离职_互联网_新浪科技_新浪网 凡客副总裁被曝离职:或因IPO受阻 2013年05月07日 00:56   每日经济新闻    我有话说     每经 ...

  8. [置顶] HMM Tutorial 隐马尔科夫模型

    有一个月没有写博客了,这一个月系统的学习了HMM model.  上周周五做了个report 感觉还好.  所以把Slide贴上来.

  9. line-height具体解释

    章:浏览器与Hack].7.3.5 应用:单行文字在垂直方向居中在网页设计中,往往为了突出标题而加入背景图案.如图7-31所看到的. watermark/2/text/aHR0cDovL2Jsb2cu ...

  10. 更好地认知Azure

    编辑人员注释:本文章由 Windows Azure 网站团队项目经理 Erez Benari 撰写. 我们的网站 http://www.windowsazure.com 包含大量信息,并且也在不断添加 ...