【转】权限管理学习 一、ASP.NET FORMS身份认证

【转】权限管理学习 一、ASP.NET Forms身份认证

说明:本文示例使用的VS2017和MVC5。
系统无论大小、牛逼或屌丝,一般都离不开注册、登录。那么接下来我们就来分析下用户身份认证。

简单实现登录、注销

以前在学习.net的时候不知道什么Forms身份认证,直接用session实现登录,效果也蛮好嘛。而且用户信息存在服务端,安全。
前端代码:

@if (string.IsNullOrWhiteSpace(ViewBag.UserName))
{
    <form action="/home/login1">
        <input type="text" name="userName" />
        <input type="submit" value="登录" />
    </form>
}
else
{
    <form action="/home/logout1">
        <div>当前用户已登录,登录名:@ViewBag.UserName</div>
        <input type="submit" value="退出" />
    </form>
}

后台代码:

public ActionResult Index()
{
    ViewBag.UserName = Session["userName"]?.ToString();
    return View();
}       

public void Login1(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了
        Session["userName"] = userName;
    else
        Session["userName"] = null;
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

public void Logout1()
{
    Session["userName"] = null;
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

是不是,简单明了。想要自己扩展或是定制什么功能都非常好用。不过我们需要维护session。比如系统重新发布,或者iis被自动重启。就会出现session丢失的情况。也就是用户会莫名其妙提升需要重新登录。体验非常不好。(这里先不讨论session服务和数据库的情况)。既然微软有一套成熟的权限管理我们为什么不用呢?

FORMS认证登录、注销

首先在web.config里开启Forms身份认证:

<system.web>
  <authentication mode="Forms"></authentication>

后台代码:

public void Login2(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了
        FormsAuthentication.SetAuthCookie(userName, true); //登录
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

public void Logout2()
{
    FormsAuthentication.SignOut();//登出
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

前台代码:

@if (!Request.IsAuthenticated)
{
    <form action="/home/login2">
        <input type="text" name="userName" />
        <input type="submit" value="登录" />
    </form>
}
else
{
    <form action="/home/logout2">
        <div>当前用户已登录,登录名:@Context.User.Identity.Name</div>
        <input type="submit" value="退出" />
    </form>
}

如此几句代码就实现了我们的登录和注销。和我们自己用session管理登录不同。Forms身份认证是直接把信息存cookie到浏览器的。通过SetAuthCookie这个方法名也可以看出来。不过Cookie信息经过了加密。
这里有必要说明session和cookie的关系。当我们利用session来维持用户状态的时候,其实也用到了cookie。

然而Forms身份认证仅仅只是把信息存了cookie,而没有在服务端维护一个对应的session。
不信你可以测试。可以用两种方式都登录,然后清除session就可以测出来了。(怎么清session?重启iis,或者修改下后台代码在重新编译访问)
【说明】用户认证为什么要存cookie?因为HTTP是一个无状态的协议。对于服务器来说,每次请求都是一样的。所以,只能通过每次请求带的cookie来识别用户了。(暂时不考虑其他方式)

自定义的身份认证标识

上面使用的登录很简单,但实际情况往往很复杂。明显正常业务需要存的用户信息会要更多。那么我们是否可以扩展身份标识呢?答案是肯定的。
后台代码:

public void Login3(string userName)
{
    if (!string.IsNullOrWhiteSpace(userName))  //为了方便演示,就不做真的验证了
    {
        UserInfo user = new UserInfo()
        {
            Name = userName,
            LoginTime = DateTime.Now
        };
        //1、序列化要保存的用户信息
        var data = JsonConvert.SerializeObject(user);

        //2、创建一个FormsAuthenticationTicket,它包含登录名以及额外的用户数据。
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, userName, DateTime.Now, DateTime.Now.AddDays(1), true, data);

        //3、加密保存
        string cookieValue = FormsAuthentication.Encrypt(ticket);

        // 4. 根据加密结果创建登录Cookie
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue);
        cookie.HttpOnly = true;
        cookie.Secure = FormsAuthentication.RequireSSL;
        cookie.Domain = FormsAuthentication.CookieDomain;
        cookie.Path = FormsAuthentication.FormsCookiePath;

        // 5. 写登录Cookie
        Response.Cookies.Remove(cookie.Name);
        Response.Cookies.Add(cookie);
    }
    Response.Redirect(Request.UrlReferrer.LocalPath);//重定向到原来页面
}

然后在Global.asax的Application_AuthenticateRequest方法:

protected void Application_AuthenticateRequest()
{
    GetUserInfo();
}

//通过coolie解密 读取用户信息到 HttpContext.Current.User
public void GetUserInfo()
{
    // 1. 读登录Cookie
    HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    try
    {
        UserInfo userData = null;
        // 2. 解密Cookie值,获取FormsAuthenticationTicket对象
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

        if (ticket != null && string.IsNullOrEmpty(ticket.UserData) == false)
            // 3. 还原用户数据
            userData = JsonConvert.DeserializeObject<UserInfo>(ticket.UserData);

        if (ticket != null && userData != null)
            // 4. 构造我们的MyFormsPrincipal实例,重新给context.User赋值。
            HttpContext.Current.User = new MyFormsPrincipal<UserInfo>(ticket, userData);
    }
    catch { /* 有异常也不要抛出,防止攻击者试探。 */ }
}

前端代码:

@{
    MyFormsPrincipal<UserInfo> user = Context.User as MyFormsPrincipal<UserInfo>;
    if (user == null)
    {
        <form action="/home/login3">
            <input type="text" name="userName" />
            <input type="submit" value="登录" />
        </form>
    }
    else
    {

        <form action="/home/logout2">
            <div>当前用户已登录,登录名:@Context.User.Identity.Name</div>
            <div>当前用户已登录,登录时间:@user.UserData.LoginTime</div>
            <input type="submit" value="退出" />
        </form>
    }
}

其实整个过程和FormsAuthentication.SetAuthCookie(userName, true); //登录是等效的。只是我们通过扩展,存了我们想要存储的数据。
过程也比较简单:

  • 构造要存储的数据
  • 序列化
  • 把序列化信息放入FormsAuthenticationTicket对象
  • 通过FormsAuthentication.Encrypt加密对象
  • 发送cookie到浏览器

这里稍微复杂点的地方就是解密然后给User赋值HttpContext.Current.User = new MyFormsPrincipal<UserInfo>(ticket, userData);
MyFormsPrincipal需要实现接口MyFormsPrincipal

public class MyFormsPrincipal<TUserData> : IPrincipal where TUserData : class, new()
{
    private IIdentity _identity;
    private TUserData _userData;

    public MyFormsPrincipal(FormsAuthenticationTicket ticket, TUserData userData)
    {
        if (ticket == null)
            throw new ArgumentNullException("ticket");
        if (userData == null)
            throw new ArgumentNullException("userData");

        _identity = new FormsIdentity(ticket);
        _userData = userData;
    }

    public TUserData UserData
    {
        get { return _userData; }
    }

    public IIdentity Identity
    {
        get { return _identity; }
    }

    public bool IsInRole(string role)//这里暂时不实现
    {
        return false;
    }
}

倒也没有什么特别,就是实例化的时候传入票据和自定义数据就好了。

授权

有了登录一般都离不开授权。微软的东西好就好在,一般都是成套成套的。

[Authorize]
public ActionResult LoginOk()
{
    return View();
}

直接给Action添加一个Authorize特性就好了,这人就会自动检查是否登录。如果没有登录自动跳转到登录页面。登录页面的设置还是在web.config里面

<system.web>
  <authentication mode="Forms" >
    <forms loginUrl="/home/index"></forms>

这种简单的授权验证明显是不够的。很多时候某些页面只有某些人才能访问。比如VIP。那么我们又要扩展了。

//继承 AuthorizeAttribute
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.Name != "农码一生")
        {
            filterContext.HttpContext.Response.Write("您不是vip用户,不能访问机密数据");
            filterContext.HttpContext.Response.End();
            return;
        }
        base.OnAuthorization(filterContext);
    }
}
[MyAuthorize]
public ActionResult LoginVIP()
{
    return View();
}

是的,就是这么简单。说了这么多,来张效果图吧:

推荐阅读:

原文地址:https://www.cnblogs.com/cjm123/p/8271206.html

时间: 2024-10-13 16:10:45

【转】权限管理学习 一、ASP.NET FORMS身份认证的相关文章

简单的ASP.NET Forms身份认证

读了几篇牛人的此方面的文章,自己也动手做了一下,就想有必要总结一下.当然我的文章质量自然不能与人家相比,只是写给从没有接触过这个知识点的朋友. 网站的身份认证我以前只知道session,偶然发现一些牛人提倡用Forms方式,微软官方也推荐这种方法.详见使用Session作为身份识别的问题 ASP.NET的身份认证方式是在web.config文件中configuration->system.web->authentication指定,如 [html] view plain copy print?

细说ASP.NET Forms身份认证

用户登录是个很常见的业务需求,在ASP.NET中,这个过程被称为身份认证. 由于很常见,因此,我认为把这块内容整理出来,与大家分享应该是件有意义的事. 在开发ASP.NET项目中,我们最常用的是Forms认证,也叫[表单认证]. 这种认证方式既可以用于局域网环境,也可用于互联网环境,因此,它有着非常广泛的使用. 这篇博客主要讨论的话题是:ASP.NET Forms 身份认证. 有一点我要申明一下:在这篇博客中,不会涉及ASP.NET的登录系列控件以及membership的相关话题, 我只想用比较

IE11下ASP.NET Forms身份认证无法保存Cookie的问题

IE11下ASP.NET Forms身份认证无法保存Cookie的问题 折腾了三四天,今天才找到资料,解决了. 以下会转贴,还没来得及深究,先放着,有空再学习下. ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="Forms"> <forms name="MyAuth" loginUrl="manager/Log

细说ASP.NET Forms身份认证 别人写的不过很透彻就转来了以后用时再看

阅读目录 开始 ASP.NET身份认证基础 ASP.NET身份认证过程 如何实现登录与注销 保护受限制的页面 登录页不能正常显示的问题 认识Forms身份认证 理解Forms身份认证 实现自定义的身份认证标识 在多台服务器之间使用Forms身份认证 在客户端程序中访问受限页面 用户登录是个很常见的业务需求,在ASP.NET中,这个过程被称为身份认证. 由于很常见,因此,我认为把这块内容整理出来,与大家分享应该是件有意义的事. 在开发ASP.NET项目中,我们最常用的是Forms认证,也叫[表单认

权限管理学习 一、ASP.NET Forms身份认证

说明:本文示例使用的VS2017和MVC5.系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单实现登录.注销 以前在学习.net的时候不知道什么Forms身份认证,直接用session实现登录,效果也蛮好嘛.而且用户信息存在服务端,安全.前端代码: @if (string.IsNullOrWhiteSpace(ViewBag.UserName)) { <form action="/home/login1"> <input t

细说ASP.NET Windows身份认证

上篇博客我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证. Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windows身份认证也会比较方便. 方便性表现为:我们不用再设计登录页面,不用编写登录验证逻辑.而且使用Windows身份认证会有更好的安全保障. 回到顶部 认识ASP.NET Windows身份认证 要使用Windows身份认证

ASP.NET Forms 身份验证

ASP.NET Forms 身份验证 在开发过程中,我们需要做的事情包括: 1. 在 web.config 中设置 Forms 身份验证相关参数.2. 创建登录页. 登录页中的操作包括: 1. 验证用户名和密码是否正确.2. 创建身份验证票证对象.3. 将身份验证票证对象加密成字符串,写入 Cookies.4. 重定向到原始请求 URL. 1. 简单演示 web.config <?xml version="1.0"?><configuration>  <s

IE11下Forms身份认证无法保存Cookie的问题

ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="Forms"> <forms name="MyAuth" loginUrl="manager/Login.aspx" defaultUrl="manager/default.aspx" protection="All&quo

[转]Forms身份认证在IE11下无法保存Cookie的问题

转自:http://www.jb51.net/article/49744.htm 这篇文章主要介绍了Forms身份认证在IE11下无法保存Cookie问题的解决方法,需要的朋友可以参考下 ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="Forms"> <forms name="MyAuth" loginUrl="