您的位置:首页 > 运维架构 > 网站架构

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

2016-02-29 16:47 549 查看
由于项目要求,还需要加入成员管理以及登陆等内容,简单介绍下自定义成员资格。

具体的项目文件可以参考我的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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据可视化 登录