基于PetShop的数据可视化网站(五):关于登录的理解

由于项目要求,还需要加入成员管理以及登陆等内容,简单介绍下自定义成员资格。

具体的项目文件可以参考我的github仓库

判断在线状态的方法

在看过的几种网站代码中,较为常见的有两种,分别是Session保存状态的方式和使用Cookie保存状态的方式,其中Session方式比较简单,但是如果网站较大的话,每个用户分一点服务器的内存,那么这种方式会离服务器宕机不远了,因此较大的网站使用Cookie保存状态是一种比较合适的方法,这种方法被称为票据。

可以做如下理解:当你的票据存在的时候,你的状态显示为在线。一旦票据不存在,那么你的状态就被显示为未登录(或者强制跳转到登录页面)

Iidentity和Iprincipal

Iidentity定义了标识对象的基本功能,里面包括了用户名,验证类型和是否经过验证三种属性,即包含了用户的基本信息。
Iprincipal定义了用户对象的基本功能,主要判断了用户的类别(管理员or普通用户)。

以下是相应的代码:

MyPrinciple.cs

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

namespace FWSync.Web
{
    public class MyPrinciple:System.Security.Principal.IPrincipal
    {
        public System.Security.Principal.IIdentity Identity
        {
            get { return this.identity; }
        }

        public bool IsInRole(string role)
        {
            //遍历用户拥有的所有角色
            foreach (string r in this.roles)
            {
                if (r == role)
                    return true;
            }
            return false;
        }

        private System.Security.Principal.IIdentity identity;
        private string[] roles;

        public MyPrinciple(System.Security.Principal.IIdentity identity, string[] roles)
        {
            this.identity = identity;
            this.roles = roles;
        }
    }
}

MyIdentity.cs

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

namespace FWSync.Web
{
    public class MyIdentity: System.Security.Principal.IIdentity
    {
        public string AuthenticationType
        {
            get { return this.authenticationType; }
        }

        public bool IsAuthenticated
        {
            get { return this.isAuthenticated; }
        }

        public string Name
        {
            get { return this.name; }
        }

        private string name;
        private bool isAuthenticated;
        private string authenticationType;

        public MyIdentity(string name,string authenticationType)
        {
            this.name = name;
            this.authenticationType = authenticationType;
            this.isAuthenticated = !string.IsNullOrEmpty(name);
        }
    }
}

用户自定义模块

我们在web.config中可以定义用户自定义模块,这个模块可以拿到HttpApplication对象,也就是我们可以通过自定义模块对页面发生的各种请求进行处理,其实简单应用的话和Global.asax差不多。

这里我们要做的是对页面初始化时的请求进行处理。页面初始化时,我们判断下请求的cookie中是否有用户票据。如果有,从票据中提取用户名,包装好后塞进HttpContext中;如果没有,则将空串塞进HttpContext中。(HttpContext我理解为上下文对象,在HttpApplication处理管道中从上到下传递,可以往里面塞一些有用的数据)

这里我并没有写未登录用户跳转到登录页面的功能,实际应用中是需要写的。

web.config中的代码如下:

 <httpModules>
     <add name="MyModule" type="FWSync.Web.MyModule" />
 </httpModules>

MyModule.cs

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

namespace FWSync.Web
{
    public class MyModule:System.Web.IHttpModule
    {

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public void Init(HttpApplication application)
        {
            application.AuthenticateRequest += 
                new EventHandler(Application_AuthenticateRequest);
        }

        //针对所有请求,就会到这里
        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpRequest request = HttpContext.Current.Request;

            //找请求的cookie里面是否有用户票据
            HttpCookie cookie = request.Cookies["Ticket"];

            string name = string.Empty;

            if (cookie != null)
            {
                string ticketstring = cookie.Value;
                //解密
                System.Web.Security.FormsAuthenticationTicket ticket
                    = System.Web.Security.FormsAuthentication.Decrypt(ticketstring);
                name = ticket.Name;
            }

            MyIdentity identity = new MyIdentity(name, "Type");

            MyPrinciple user = new MyPrinciple(identity, new string[] { });

            HttpContext context = HttpContext.Current;
            context.Items.Add("User", user);
        }
    }
}

表现层的使用方式

在表现层中,如果是登录界面,我们需要做的是创建一个票据;如果是其他页面,我们则需要拿到HttpContext中的内容,并判断是否登录成功。

在Login.aspx中,我们只需要对用户进行验证后将用户名加密写入票据中即可,其代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class Login : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void btnLogin_Click(object sender, EventArgs e)
    {
        string name = this.tbxName.Text;
        string password = this.tbxPassword.Text;

        bool isexist = System.Web.Security.Membership.ValidateUser(name, password);

        if (isexist)
        {
            //生成了票据
            System.Web.Security.FormsAuthenticationTicket ticket
                = new System.Web.Security.FormsAuthenticationTicket(
                    2,
                    name,
                    DateTime.Now,
                    DateTime.Now.AddHours(12),
                    true,
                    string.Empty
                    );

            //这里需要存储产生的票据
            HttpCookie cookie = new HttpCookie("Ticket");

            //序列化并加密
            string ticketstring =
                System.Web.Security.FormsAuthentication.Encrypt(ticket);

            cookie.Value = ticketstring;
            cookie.Expires = DateTime.Now.AddHours(12);

            this.Response.Cookies.Add(cookie);

            //这里应该跳转到登录成功的界面之类的地方,先转向主页也一样
            this.Response.Redirect("~/Default.aspx");
        }
    }
}

而在Default.aspx中,我们可以通过HttpContext的内容判断用户票据内容,如果登录,显示用户名;如果未登录,直接显示未登录。

            //如果登录,则显示用户名
            HttpContext context = this.Context;
            MyIdentity identity = context.Items["User"] as MyIdentity;
            System.Security.Principal.IPrincipal user = context.Items["User"] as System.Security.Principal.IPrincipal;

            if (user.Identity.IsAuthenticated)
            {
                this.lblLogSta.Text = string.Format("欢迎 {0}", user.Identity.Name);
            }
            else
            {
                this.lblLogSta.Text = "未登录";
            }

另一种方法

上面写到的功能,微软已经写好了一些内置方法,因此可以略去多行代码。

1、首先可以将MyModule.cs中下列内容进行修改:

 //MyIdentity identity = new MyIdentity(name, "Type");
            System.Security.Principal.GenericIdentity identity
                = new System.Security.Principal.GenericIdentity(name, "Type");
//MyPrinciple user = new MyPrinciple(identity, new string[] { });
            System.Security.Principal.GenericPrincipal user
                = new System.Security.Principal.GenericPrincipal(identity,new string[] { } );

也就是删去MyIdentity.cs和MyPrinciple.cs后,均采用默认的方式创建。

2、Default.aspx中也可以通过默认的方式拿到用户对象,代码可以精简如下:

HttpContext context = this.Context;
System.Security.Principal.IPrincipal user = this.User;

3、Default.aspx中登录状态的显示可以使用Login控件进行显示,可以删去if (user.Identity.IsAuthenticated)代码段

4、还可以删去MyModule用户自定义模块,同时需要删去Login页面中创建票据的部分和Default页面中登录判断部分,增加web.config中设置部分。

web.config增加部分:

    <authentication mode="Forms">
      <forms name="Ticket"></forms>
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>

这里是指采用表单验证的方式,生成的票据名称为Ticket,所有的页面禁止未登录的用户访问

Login.aspx中判断部分改为如下代码:

if (isexist)
{
    System.Web.Security.FormsAuthentication.RedirectFromLoginPage(name, true);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值