ADO.NET Data Service:如何做身份验证
2010-02-28 23:39
405 查看
ADO.NETDataService是基于WCF的一套REST风格的服务,但是它在很多方面又与WCF很不一样,典型的情况就是在身份验证方面。这篇文章专门来说一说如何为其实现身份验证。
1.采用Windows验证方式。
这种方式总是最简单也是最安全的。基本上我们也无需做太多事情。
web.config中配置
.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;}
DataService里面,我们要通过所谓的QueryInterceptor进行拦截
.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;}
这样,我们就实现了目的:该服务(或者说其他的网站资源),只允许Chenxizhang-pc\chenxizhang这个账号能访问到。
接下来,客户端中应该怎么做呢?
.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;}
就会发生一个错误
.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.config中的身份验证模式改为不验证(也就是说由我们自定义验证)
.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;}
然后,我们将上面这个模块注册到配置文件中
.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;}
配置好之后,我们再次运行一下客户端,收到了如下的错误。这一点都不奇怪,因为我们并没有传递身份过来。
那么客户端应该如何传递身份呢
.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;}
这样的话,我们就能如愿看到结果了
1.采用Windows验证方式。
这种方式总是最简单也是最安全的。基本上我们也无需做太多事情。
web.config中配置
<authenticationmode="Windows"/> <authorization> <allowusers="Chenxizhang-pc\chenxizhang"/> <denyusers="*"/> </authorization>
.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;}
DataService里面,我们要通过所谓的QueryInterceptor进行拦截
[QueryInterceptor("Customers")] publicExpression<Func<Customers,bool>>OnQueryCustomers() { if(!HttpContext.Current.User.Identity.IsAuthenticated) thrownewAuthenticationException(); else return(c)=>true; }
.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;}
这样,我们就实现了目的:该服务(或者说其他的网站资源),只允许Chenxizhang-pc\chenxizhang这个账号能访问到。
接下来,客户端中应该怎么做呢?
localhost.NorthwindEntitiescontext=newlocalhost.NorthwindEntities( newUri("http://localhost:2549/NorthwindService.svc/")); context.Credentials=System.Net.CredentialCache.DefaultNetworkCredentials; ////查询 varquery=fromcincontext.Customers wherec.City.Equals("London") selectc; Console.WriteLine(query.ToString()); foreach(variteminquery) { Console.WriteLine(item.CompanyName); }
现在我的身份是合法的,所以能看到结果
但是如果我把下面这一句去除掉
<allowusers="Chenxizhang-pc\chenxizhang"/>
.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;}
就会发生一个错误
很好,我们这样就实现了身份验证了。
等一下,这样是否就真的万事大吉了呢?大家要知道,不是任何场合都有机会使用Windows验证的,例如在internet上,可能就无法使用Windows验证方式。
那么,是不是可以使用传统的Forms验证呢?如果在一个网站内部,那么看起来确实可以:先让用户去一个页面(Login.aspx)进行登录,此时它的凭据会保存起来,然后再访问服务的话就拥有了身份。
但是,问题是,如果仅仅在网站内部使用,那么有什么必要用DataService呢?为什么不直接用EDM去存取数据库呢?
好吧,那么,如果我们既希望在外部能访问到这个DataService,又不想用Windows验证,并且我们也无法使用Forms验证,那么该怎么办呢?答案是自定义验证。
首先,我们编写一个HttpModule
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
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)
{
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)));
}
else
{
stringcredential=ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(GetBase64CredentialsFromHeader()));
string[]usernameandpassword=credential.Split(':');
context.Context.User=newMyPrinciple(
newMyIdentity(usernameandpassword[0],Authenticate(usernameandpassword[0],usernameandpassword[1])));
}
}
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;}
然后,我们将web.config中的身份验证模式改为不验证(也就是说由我们自定义验证)
<authenticationmode="None"/>
.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;}
然后,我们将上面这个模块注册到配置文件中
<addname="DataServiceAuthentication"type="DataServiceAuthenticationModule.AuthenticationModule,DataServiceAuthenticationModule"/>
.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;}
配置好之后,我们再次运行一下客户端,收到了如下的错误。这一点都不奇怪,因为我们并没有传递身份过来。
那么客户端应该如何传递身份呢
context.Credentials=newSystem.Net.NetworkCredential("chenxizhang","password");
.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;}
这样的话,我们就能如愿看到结果了
写到这里,我想很多朋友就看明白了,我们做了一个自定义的HttpModule,接管了请求的身份验证过程。那么现在的做法是直接比较用户名和密码,是不是很不合理呢?
当然,正式的环境下我们不能这么做,但是你既然拿到了username,和password,其实你要怎么验证都不重要了。
.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;}
相关文章推荐
- ADO.NET Data Service如何直接支持用Json格式返回数据
- ADO.NET Data Service中如何自定义Operation
- 如何在AJAX应用中访问ADO.NET Data Service(续)——基于jquery框架
- 如何在AJAX应用中访问ADO.NET Data Service
- 如何在AJAX应用中访问ADO.NET Data Service
- ADO.NET Data Service中如何自定义Operation
- 如何在AJAX应用中访问ADO.NET Data Service(续)——基于jquery框架
- ADO.NET Data Service如何直接支持用Json格式返回数据
- ADO.NET Data Service:如何做身份验证
- MOSS 2010:Visual Studio 2010开发体验(20)——使用ADO.NET Data Service快速访问SharePoint列表数据
- ADO.NET 第三课 如何用sqldataadapter 来填充DataSet.
- Consuming ADO.NET Data Service (Astoria) from Silverlight
- ASP.NET4.0 Ajax实例 –Javascript调用 ADO.NET Data Service实现数据库操作
- ADO.NET Data Service 二 绑定数据类
- Teched2008 DEV301 ADO.NET Data Service资料下载
- 如何:实现简单的 Forms 身份验证(asp.net)
- ado.net 集成身份验证代码
- ADO.NET Data Service之CRUD操作
- Hosting the Data Service (ADO.NET Data Services)
- 再谈谈ADO.NET Data Service 数据格式(xml和json)