65.9K
CodeProject 正在变化。 阅读更多。
Home

无 Cookie 的 ASP.NET 表单身份验证

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (41投票s)

2002 年 8 月 25 日

3分钟阅读

viewsIcon

587909

downloadIcon

3298

他们说在 .NET 中不可能使用无 cookie 的表单身份验证。 事实上是可以的,而且相对容易实现!

无 Cookie 的表单身份验证

为什么,什么时候?

他们说这是不可能的。 事实上是可以的,而且相对容易实现!

许多公司和人希望从他们的生活中排除 cookie 的使用。 部分原因是据说不安全,部分原因是他们认为没有理由使用它。

在我的情况下,强制要求不使用 cookie,但要创建一个表单登录页面。 当然,我首先使用了正常的表单身份验证,因为我相信,老大哥不会犯使用 cookie 这样的错误。

他们确实犯了。 在搜索了所有论坛,寻找如何跳过 cookie 使用后,我发现的只是这个

困难的方法

如果您将编码后的 cookie 作为 GET 参数传递给 Response.Redirect() 函数,系统将正常工作:用户将一直处于登录状态,直到解析器找到作为 GET 参数的 cookie,否则 cookie 并不容易,而且毫无意义。

以下是实现无 cookie 身份验证的“get”方法的代码片段

FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;

//create a valid ticket for forms authentication
tkt = new FormsAuthenticationTicket(1, userName, DateTime.Now,
DateTime.Now.AddMinutes(30), false, "your custom data");
//get the string representation of the ticket cookiestr = FormsAuthentication.Encrypt(tkt); //redirect to the return URL using the cookie in the address field //In the web.config, we called out auth. ASPXFORMSAUTH2, so set that value string strRedirect = Request["ReturnUrl"] + "?.ASPXFORMSAUTH2=" + cookiestr; Response.Redirect(strRedirect, true);

我告诉你,这是没用的。 完全令人不愉快,而且不安全(你必须更改所有链接,当然你不会这样做)

以下是你可以做到这一点的方法

配置

除了“none”之外,不需要任何身份验证标签。 web.config 中的下一行将告诉框架不要将会话 ID 存储在 cookie 中,而是作为特殊目录添加到地址字段中。

<sessionState cookieless="true" timeout="20" />

添加此行后,地址字段将始终如下所示

https:///samplecookieless/(lvymatawljpjtl55d4awjg55)/login.aspx

如您所见,在每个请求中,会话 ID 都作为目录传递。 来自 MS 的非常聪明的解决方案! 当您要创建一个带有 get 参数的链接到另一个页面时,您必须注意它,因为在地址中没有会话 ID 的情况下调用 aspx 将创建一个新会话。 因此,要创建一个具有 GET 参数的链接,请执行以下操作

string url =
string.Format(
// we build the whole link. Firstly, we get our host name
 "http://" + Request.Headers["Host"] + "/" + 
// then the path of the request, and append the session ID, as shown above
 Request.ApplicationPath + 
 "/(" + Session.SessionID + 
// simply add the target page with the HTTP-GET parameters.
 ")/Main.aspx?{0}={1}&{2}={3}",
 "State", state.ToString(),
 "Lang", langID.ToString()
);

(好的,我需要它。通常人们不关心 GET 参数,所以你可能不需要它。)

编码部分

global.asax.cs 中,添加

private void InitializeComponent()
{  // This tells the global to catch all session initialization events,
   // So before every page load, we will have the Global_Acq. called! Good starting!
   this.AcquireRequestState += new
   System.EventHandler(this.Global_AcquireRequestState);
}
private
void Global_AcquireRequestState(object sender, System.EventArgs e)
{ 
	//This tells the global to check whether code "Name-John" is in the session 
	//variable, called "Authenticated". To say it simple, 
	//checks, whether someone set this 
	//variable.
	if((string)Session["Authenticated"] != "Name-John")
	// If yes, do nothing, so the requested page will load.
		{
		// If it's not set yet, redirect to the login page, 
		// if the caller is not the login page already. If it is, we don't 
		//want loops, so let is load
		if(!Request.Path.EndsWith("login.aspx"))
		{
			Response.Redirect("login.aspx");
			Response.End();
		}
	}
}

如果用户输入了有效的代码(以您喜欢的方式检查它们),则在 login.apsx.cs 中,将会话变量 Authenticated 设置为代码 Name-John,以便全局变量允许用户下载页面。

Session["Authenticated"] = "Name-John";
//the auth is successfull, so send the user to the page
Response.Redirect("default.aspx", true);

如您所见,这是一个纯粹的重定向函数。 未使用任何 ASP.NET 表单身份验证。 在 default.aspx 上,放置任何你想要的内容。 这些控件将是安全的。 如果要注销用户,请调用此代码

//signs out
Session.Abandon();
//redirects to itself. This will redirect to login.aspx, cos we are signed out
Response.Redirect(Request.Path,true);

其他需要了解的知识

单击注销后,用户将返回到 login.aspx。 如果他按返回,他可以看到来自浏览器缓存的页面,但无法单击任何内容。 设置缓存过期时间可能是明智的。

如果您按下 [后退],然后按下 [刷新],浏览器将要求“在不重新发送信息的情况下无法刷新页面”,并提示“重试/取消”。

通常,当有人按下重试时,密码会再次发送,并且用户会再次登录。 好吧,在我们的例子中不是这样

您可以尝试,这种方法确实不使用 cookie:在 Internet Explorer 中,转到工具/Internet 选项。 转到隐私,并阻止所有 cookie,然后尝试登录和注销。

如果您有任何问题/意见,请发送给我!

真诚的,Adam

© . All rights reserved.