如何在Web应用程序中实现自定义身份验证对话框
2010-02-28 23:38
615 查看
这个标题可能并不太准确,我这样来描述一下我们的意图吧:
我们知道在Web应用程序中有几种主要的身份验证方式,典型的就是Windows验证和Forms验证。如果设置为Windows验证的话,那么既可以自动使用用户当前身份登录(如果在一个可信任的环境中),也可以弹出一个对话框要求用户输入用户名和密码。
再来Forms验证,顾名思义,它是有一个表单来进行验证的,在web.config中,我们通常需要指定一个loginUrl。这样用户如果没有得到授权,则需要转到这个页面输入用户名和密码。
但是,也有的朋友跟我提到,如果我们使用Forms验证,能不能也弹出一个对话框让用户输入用户名和密码呢?这的确是一个不错的问题。
可惜的是,Forms验证无法提供这样的功能,但我们确实可以通过自定义验证来实现
那么,在后面到底发生了什么呢?是怎么弹出这个对话框的呢?
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这个对话框其实是浏览器弹出来的。浏览器收到了一个Response,内容为Unauthorized,所以它知道服务器端需要进行验证,所以它弹出了这个对话框。为了说明这一点,我们可以来看一下其他的浏览器弹出的对话框。下面这个是Googlechrome浏览器弹出的
下面这个是MozillaFirefox浏览器弹出的
那么,接下来我们看看,我们输入的用户名和密码是怎么发送给服务器的呢
我们看到了这样一串文本:
Y2hlbnhpemhhbmc6cGFzc3dvcmQ=
这里就是包含了我们输入的用户名和密码。注意,它并没有被加密。我们可以通过下面的几行代码很容易地将其还原为明文的字符串
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
我们知道在Web应用程序中有几种主要的身份验证方式,典型的就是Windows验证和Forms验证。如果设置为Windows验证的话,那么既可以自动使用用户当前身份登录(如果在一个可信任的环境中),也可以弹出一个对话框要求用户输入用户名和密码。
再来Forms验证,顾名思义,它是有一个表单来进行验证的,在web.config中,我们通常需要指定一个loginUrl。这样用户如果没有得到授权,则需要转到这个页面输入用户名和密码。
但是,也有的朋友跟我提到,如果我们使用Forms验证,能不能也弹出一个对话框让用户输入用户名和密码呢?这的确是一个不错的问题。
可惜的是,Forms验证无法提供这样的功能,但我们确实可以通过自定义验证来实现
usingSystem; usingSystem.Text; usingSystem.Web; usingSystem.Security.Principal; namespaceDataServiceAuthenticationModule { publicclassAuthenticationModule:IHttpModule { conststringaccessDeniedStatus="拒绝访问"; conststringaccessDeniedHtml="<html><body>401您的请求被拒绝,因为没有通过身份验证</body></html>"; conststringrealmFormatString="Basicrealm=\"{0}\""; conststringauthServerHeader="WWW-Authenticate"; conststringauthClientHeader="Authorization"; conststringbasicAuth="Basic"; #regionIHttpModule成员 publicvoidDispose() { } publicvoidInit(HttpApplicationcontext) { context.AuthenticateRequest+=newEventHandler(context_AuthenticateRequest); } voidcontext_AuthenticateRequest(objectsender,EventArgse) { HttpApplicationcontext=(HttpApplication)sender; if(context.Request.Headers["Authorization"]==null) { UnAuthorization(context); } else { stringcredential=ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(GetBase64CredentialsFromHeader())); string[]usernameandpassword=credential.Split(':'); boolisAuthenticate=Authenticate(usernameandpassword[0],usernameandpassword[1]); if(!isAuthenticate) { UnAuthorization(context); } context.Context.User=newMyPrinciple( newMyIdentity(usernameandpassword[0],isAuthenticate)); } } privatestaticvoidUnAuthorization(HttpApplicationcontext) { context.Response.ContentEncoding=Encoding.GetEncoding("GB2312"); context.Response.StatusCode=401; context.Response.StatusDescription=accessDeniedStatus; context.Response.Write(accessDeniedHtml); //TODO:notsurethisisquiterightwrtrealm. context.Response.AddHeader(authServerHeader, string.Format(realmFormatString,context.Request.Url.GetLeftPart(UriPartial.Authority))); } boolAuthenticate(stringusername,stringpassword) { //yourcodelogicheretoauthenticateuser if(username!="chenxizhang"||password!="password")returnfalse; else returntrue; } stringGetBase64CredentialsFromHeader() { stringcredsHeader=HttpContext.Current.Request.Headers[authClientHeader]; stringcreds=null; intcredsPosition= credsHeader.IndexOf(basicAuth,StringComparison.OrdinalIgnoreCase); if(credsPosition!=-1) { credsPosition+=basicAuth.Length+1; creds=credsHeader.Substring(credsPosition, credsHeader.Length-credsPosition); } return(creds); } #endregion } publicclassMyPrinciple:IPrincipal { privateIIdentity_id; publicMyPrinciple(IIdentityid) { _id=id; } publicIIdentityIdentity { get{return_id;} } publicboolIsInRole(stringrole) { thrownewNotImplementedException(); } } publicclassMyIdentity:IIdentity { privatebool_isAuthenticated=false; privatestring_name; publicMyIdentity(stringname,boolisAuthenticated) { _isAuthenticated=isAuthenticated; _name=name; } publicstringAuthenticationType { get{thrownewNotImplementedException();} } publicboolIsAuthenticated { get{return_isAuthenticated;} } publicstringName { get{return_name;} } } }
那么,在后面到底发生了什么呢?是怎么弹出这个对话框的呢?
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这个对话框其实是浏览器弹出来的。浏览器收到了一个Response,内容为Unauthorized,所以它知道服务器端需要进行验证,所以它弹出了这个对话框。为了说明这一点,我们可以来看一下其他的浏览器弹出的对话框。下面这个是Googlechrome浏览器弹出的
下面这个是MozillaFirefox浏览器弹出的
那么,接下来我们看看,我们输入的用户名和密码是怎么发送给服务器的呢
我们看到了这样一串文本:
Y2hlbnhpemhhbmc6cGFzc3dvcmQ=
这里就是包含了我们输入的用户名和密码。注意,它并没有被加密。我们可以通过下面的几行代码很容易地将其还原为明文的字符串
usingSystem; usingSystem.Text; namespaceConsoleApplication1 { classProgram { staticvoidMain(string[]args) { stringtoken="Y2hlbnhpemhhbmc6cGFzc3dvcmQ="; byte[]buffer=Convert.FromBase64String(token); stringoutput=Encoding.ASCII.GetString(buffer); Console.WriteLine(output); Console.Read(); } } }
这是用冒号隔开的字符串。
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
相关文章推荐
- 如何在Web应用程序中实现自定义身份验证对话框
- 如何实现基于消息/传输安全验证机制下的windows身份验证过程、无任何验证
- 如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- 如何实现某一目录的forms身份验证
- [来自msdn]如何:实现简单的 Forms 身份验证
- 教你如何实现微信小程序与.net core应用服务端的无状态身份验证
- 如何实现某一目录的forms身份验证
- 如何实现某一目录的forms身份验证
- 如何:实现简单的 Forms 身份验证
- 如何实现从WinForm中打开一个需要身份验证的Web系统?
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
- 介绍如何通过加密算法实现数据的完整性、机密性及身份验证
- 使用struts2自定义拦截实现统一的身份验证模式
- 如何实现某一目录的forms身份验证
- 如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- [导入]如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- 如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- 如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)