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






4.35/5 (41投票s)
2002 年 8 月 25 日
3分钟阅读

587909

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