您的位置:首页 > 其它

如何在Web应用程序中实现自定义身份验证对话框

2010-02-28 23:38 615 查看
这个标题可能并不太准确,我这样来描述一下我们的意图吧:

我们知道在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;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: