登录 Cookie实现

Profile Picture
- Published on Apr 1, 2020🌏 Public

Cookie判别登录状态

Cookie可以实现关闭浏览器再打开,还保留登录状态。

cookie存储登录信息的方式,需要保证数据不易被破解。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace UserLogin.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            //加入登录判断,如果username有值,就正常访问,否则跳转到登录页
            if (Request.Cookies["u"]== null)
            {
                return Redirect("/home/loginpage");
            }
            else
            {
                return View();
            }

        }
        public ActionResult LoginPage()
        {
            return View();
        }
        public JsonResult Login(string username)
        {
            //直接设置登录名的cookie,不验证密码
            Response.Cookies.Add(new HttpCookie("u")
            {
                HttpOnly = true,
                Expires = DateTime.Now.AddDays(1),
                Value = username
            });
            return Json(new
            {
                message = "登录成功"
            }, JsonRequestBehavior.AllowGet);
        }
    }
}

我们上面这种明文加密的方式是显然不可取的。 现实中我们使用Cookie储存用户登录凭证,都有验证数据是否伪造的能力。

换句话说,就是Cookie中存储的用户身份凭证信息,一定经过加密存储的,并且伪造的加密串可以被鉴别。

ASP.NET自带的身份凭证验证

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace UserLogin.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            //加入登录判断,如果username有值,就正常访问,否则跳转到登录页
            if (!User.Identity.IsAuthenticated)
            {
                //User.Identity.Name //用户名
                return Redirect("/home/loginpage");
            }
            else
            {
                return View();
            }
        }
        public ActionResult LoginPage()
        {
            return View();
        }
        public JsonResult Login(string username)
        {
            //直接设置登录名的cookie,不验证密码
            FormsAuthentication.SetAuthCookie(username, true);
            return Json(new
            {
                message = "登录成功"
            }, JsonRequestBehavior.AllowGet);
        }
    }
}

loginUrl:登录页地址 name:cookie名 timeout:过期时间(分钟) slidingExpiration:是否自动续期

  <system.web>
    <authentication mode="Forms">
        <forms loginUrl="/home/loginpage" name="WoDeShengFeng" timeout="60"  slidingExpiration="true"></forms>
    </authentication>
   </system.web>

手动创建身份凭证Cookie

public JsonResult Login(string username)
{
    //1.建立一个身份票据
    //  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(username, true, FormsAuthentication.Timeout.Minutes);
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,username,DateTime.Now,DateTime.Now.Add(FormsAuthentication.Timeout), true, "管理员,会计");
    //2.加密,获得加密后的字符串
    var secretStr= FormsAuthentication.Encrypt(ticket);
    //3.写入到cookie中
    Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName)
    {
        HttpOnly = true,
        Path=FormsAuthentication.FormsCookiePath,
            Expires= DateTime.Now.Add(FormsAuthentication.Timeout),
            Value= secretStr
    });
    return Json(new
    {
        message = "登录成功"
    }, JsonRequestBehavior.AllowGet);
}

ASP.NET Forms身份验证限制访问

将Home/Index的身份验证删除了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace UserLogin.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult LoginPage()
        {
            return View();
        }
        public JsonResult Login(string username)
        {
            //1.建立一个身份票据
            //  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(username, true, FormsAuthentication.Timeout.Minutes);
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,username,DateTime.Now,DateTime.Now.Add(FormsAuthentication.Timeout), true, "管理员,会计");
            //2.加密,获得加密后的字符串
            var secretStr= FormsAuthentication.Encrypt(ticket);
            //3.写入到cookie中
            Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName)
            {
                HttpOnly = true,
                Path=FormsAuthentication.FormsCookiePath,
                 Expires= DateTime.Now.Add(FormsAuthentication.Timeout),
                 Value= secretStr
            });
            return Json(new
            {
                message = "登录成功"
            }, JsonRequestBehavior.AllowGet);
        }
    }
}

system.web配置节中可以设置授权

   <authorization>
     <!--允许匿名用户访问-->
      <allow users="?"/>
      <!--拒绝匿名用户-->
      <deny users="?"/>
      <!--允许所有用户访问-->
      <allow users="*"/>
      <!--拒绝所有用户访问-->
      <deny users="*"/>
      <!--允许admin和admin2访问-->
      <allow users="admin,admin2"/>
      <!--拒绝admin和admin2访问-->
      <deny users="admin,admin2"/>
      <!--允许角色为管理员和超级管理员的用户访问-->
      <allow roles="管理员,超级管理员"/>
      <!--拒绝角色为管理员和超级管理员的用户访问-->
      <deny roles="管理员,超级管理员"/>
    </authorization>

按照这个规则,我们还可以对特定目录或页面进行访问限制: configuration配置节下: path可以写路径或者具体页面

  <location path="product">
    <system.web>
      <authorization>
        <deny users="?"/>
      </authorization>
    </system.web>
  </location>

角色访问

https://www.cnblogs.com/pinko/archive/2013/05/02/3053965.html

要实现角色控制访问,需要自行进行用户身份的识别,自己去构建User身份信息。 Global.asax文件中:

protected void Application_AuthenticateRequest() {
    var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if (cookie != null)
    {
        //从cookie中获取加密后的字符串
        var secretStr=cookie.Value;
        //根据字符串,调用Decrypt方法解密出票据
        FormsAuthenticationTicket  ticket =  FormsAuthentication.Decrypt(secretStr);
        //判断是否过期
        if (!ticket.Expired) {
            //未过期,获取用户名和附加数据,并且建立角色的字符串数组
            string username = ticket.Name;
            string userData = ticket.UserData;
            string[] roles = userData.Split(',');
            //建立身份凭据
            GenericIdentity identity = new GenericIdentity(username);
            GenericPrincipal principal = new GenericPrincipal(identity, roles);
            //将用户身份设置到请求的上下文中
            Context.User = principal;
        }
    }
}

练习

  1. 数据库建立:用户表,loginname,password,role;插入几条数据
  2. 做个登录页,实现登录功能
  3. User/Index 用户管理页,要求必须是管理员身份才能访问
  4. Product/Index 产品管理业,管理员和产品管理员都能访问
  5. 登录的时候,如果有ReturnUrl,那么登录完成后,跳转回ReturnUr指定的页面