文章目录
  1. 1. Forms认证
  2. 2. Session认证
  3. 3. Forms和Session双认证
  4. 4. 总结

以往用forms认证和session做登陆验证,这几天仔细看了一下这方面的一些知识,发现以前很多概念都是很模糊和错误的。所以想总结一下。


在用asp.net做网站登录验证的时候,让网站或者系统后台必须登陆才能访问时,很多时候会用到forms认证,也有些人同时用session加一层验证。

Forms认证

  • forms认证,用的是cookie来进行验证,cookie是保存在客户端的,其安全性来说我也不是很清楚,都说cookie保存在客户端很容易被截取被改动,但我认为一般的人很难截取
    cookie,至少我搜了一晚上也没找到怎么截取后的cookie来实现模仿登陆,可能我很菜不知道,求高人指点。所以我认为,在一般的网站中只用forms认证相对来说已经够用了。

  • forms认证的配置也很简单,用mvc上的一个例子,只需要在Web.config中的内加上配置节,如:

    1
    2
    3
    4
    5
    <system.web>
    <authentication mode="Forms">
    <forms loginUrl="~/Home/Login" timeout="60" />
    </authentication>
    </system.web>
  • 并且在登陆验证账号密码正确后,调用这个方法来保存cookie,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    private void SetCookie(string userName,string userRole)
    {
    //加cookie
    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,//版本号
    userName,//用户名
    DateTime.Now,//生成票据的时间
    DateTime.Now.AddMinutes(30),//cookie过期时间
    false,//cookie是持久的为true,否则为false
    userRole//用于辨认用户角色

    );

    string eTicket = FormsAuthentication.Encrypt(authTicket);//加密cookie
    HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, eTicket);
    authCookie.HttpOnly=true ;//防止javascript访问,可提高安全性能
    //authCookie.Secure = true;这个为true时候,只有https才能访问
    Response.Cookies.Add(authCookie);
    //当检测cookie快过期,会自动扩展,不必监听
    ///1.userName可以用来存储用户名(比如学生学号),这个字段可以当做全局的来调用,如插入数据的时候填写记录用户名,在后台可以直接用User.Identity.Name直接调用userName

    //2.userRole可用来标识身份,如一个选课系统中,管理员是admin,教师是teacher,学生是student
    //想要用调用userRole时候可以用下面的方法
    //var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    //var ticket = FormsAuthentication.Decrypt(cookie.Value);
    //string role = ticket.UserData;
    //这也可以调用userName
    //string name=ticket.Name;
    }
  • 这样做后,只需要在控制器或者方法上添加 [Authorize]就行,当未登录用户直接访问当前方法的时候,就会跳转到web.config配置的路径了,达到限制访问的效果,如下面:

    1
    2
    3
    4
    5
    [Authorize]
    public ActionResult Index()
    {
    return View();
    }
  • 但这种做法只能识别一种身份的,就是说只能识别登陆与未登录用户,并不会识别当前的访问者是什么身份,如教师和学生,当我们想要做到教师可以访问,学生不可访问这种方法,还得在Global.asax添加这一段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //forms认证需要,在控制器上加上[Authorize(Roles = "admin")]可控制权限
    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null || authCookie.Value == "")
    {
    //Construst the GeneralPrincipal and FormsIdentity objects
    return;
    }
    FormsAuthenticationTicket authTicket = null;
    try
    {
    authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch
    {
    return;
    }
    //get the role
    string[] roles = authTicket.UserData.Split(new char[] { ';' });
    if (Context.User != null)
    {
    Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
    }
    }
  • 然后通过在控制器或方法上面添加[Authorize(Roles = “xxx”)]就可以做到这个方法限制只能是xxx这种用户才可以访问,如

    1
    2
    3
    4
    5
    6
    [Authorize(Roles = "admin")]//admin是我在登陆设置的cookie中的UserRole
    public ActionResult Index()
    {
    return View();
    }
    //这样就可以做到只有admin标识的用户才可访问,其他如教师、学生访问这个方法就会跳转到登陆页。

当然这只是MVC上的做法,WebForm形式的校验方法其实更简单,这里就不多说,google一下一大把。

Session认证

  • session验证,一般很多人都会用这个来验证登陆,这可以说是最简单的了。用session验证登陆其实比forms认证是更安全一些的,毕竟session是保存在服务器端的,被篡改的可能更难。但session是保存在服务器的内存中的(有些人说是保存在文件中的,我也没搞清楚到底是在哪,但我现在认为默认是保存在内存中的),所以说session是会消耗服务器资源的,当网站访问量很大的时候,session的数量就很可观了,当服务器内存不足或者其他原因就崩溃了。
    对于webform,只要在pageload里面验证一下if(Session[“xxx”]==null) Resopnse.Redirect(“../login.aspx”);也就是说当session为空的时候就跳转到登陆页面。如:

    1
    2
    3
    4
    5
    6
    7
    protected void Page_Load(object sender, EventArgs e)
    {
    if(Session["user"]==null)
    {
    Response.Redirect("~/login.aspx");
    }
    }
  • 但这样做有点麻烦,就是需要每个页面都要在PageLoad里面判断session是否为空。这时候最好就写一个继承的类,让需要验证登陆的页面都继承一个BasePage类,在BasePage页面override OnInit事件(BasePage页面要继承System.Web.UI.Page),这样就可以实现当请求子页面时候都验证一次session而且不用每个页面都复制粘贴代码了。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    protected override void OnInit(EventArgs e)
    {
    if (Session["uInfo"] == null)
    {
    //1.判断用户是否勾选记住三天免登陆
    if (Request.Cookies[“uid”] != null)
    {
    BlogUserBLL bll = new BlogUserBLL();
    //2.通过cookie里传入的数据得到数据实体
    BlogUser umodel = bll.GetModel(int.Parse(Request.Cookies["uid"].Value));
    //3.将实体存入session中
    Session["uInfo"] = umodel;
    return;
    }
    //4.跳转到登陆页面
    Response.Redirect("/Login.aspx");
    }
    base.OnInit(e);
    }
  • 而对于MVC下的,就写一个BaseController的类,在BaseController里面写验证session,需要验证登陆的页面只要继承BaseController类就可以了。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class BaseController :Controller
    {
    //在当前的控制器里面所有的方法执行之前。都先执行此代码

    public bool IsCheckUserLogin = true;
    public UserInfo LoginUser { get; set; }
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
    base.OnActionExecuting(filterContext);

    var items = filterContext.RouteData.Values;


    if (IsCheckUserLogin)
    {




    if (filterContext.HttpContext.Session["loginUser"] == null)
    {
    filterContext.HttpContext.Response.Redirect("/UserLogin/Index");
    }
    else
    {
    LoginUser = filterContext.HttpContext.Session["loginUser"] as UserInfo;
    }
    }
    }
    }

Forms和Session双认证

  • 在刚学到forms认证时候,也没有真正弄清楚forms认证和session认证是怎么回事,当时觉得反正大家都这样用,我也这样做,肯定就不会错了。所以,很多时候我们就是session和Forms认证一起用,在pageload里面验证session是否为空,又用forms认证,其实这样做也挺好的,不过当时没有意识到用BasePage类,在每个页面都是复制粘贴代码,导致很乱很难维护,一直也没理清是怎么回事。

  • 在一般的项目中,同时用session和forms我认为是最安全的,一般也建议这样做。

总结

  • 在我一般的建站中,用到session的时候一般是登陆的时候记录一下用户名,以便在用户操作时候记录这个用户的用户名。

  • 校内的服务器性能比较差,要把内存和带宽的利用做得很好,才能承受更大的访问量。用cookie会在每次访问页面时发送到服务器,影响到服务器带宽,而session则会消耗服务器内存。

  • 所以,最后我认为,为了减少服务器负担,在服务器不给力和要满足一定的安全前提下,尽量少用session存储数据量较大的数据。我用了forms认证,就没必要再用session了。当需要用到全局的用户名的时候,直接用cookie记录用户的身份(管理员、教师、学生)和当前访问人的用户名,调用cookie就好了。

  • 以上

文章目录
  1. 1. Forms认证
  2. 2. Session认证
  3. 3. Forms和Session双认证
  4. 4. 总结