Web Service的安全机制4969.docx
Web Serrvicce的安安全机制制一个 WWeb 应用程程序具有有的一个个重要部部分是:能够识识别用户户和控制制对资源源的访问问。确定定请求实实体身份份的行为为称为身身份验证证。通常常,用户户必须出出示凭据据(如名名称/密密码对)以以便进行行身份验验证。一一旦经过过验证的的标识可可用,就就必须确确定此标标识是否否可以访访问给定定的资源源。Web Serrvicce的安安全机制制主要从从两个方方面考虑虑, 一一个是利利用Wiindoows安安全机制制,另一一个就是是利用SSOAPP标头,下下面分别别进行讨讨论。一、 利用Wiindoows安安全机制制我们来做做一个实实验,首首先做一一个最简简单的WWeb服服务程序序。<WebbMetthodd()>> PuubliicFuuncttionn HeellooWorrld() AAsSttrinng HeellooWorrld = ""Helllo Worrld""EndFFuncctioon完成以后后,打开开Intternnet服服务管理理器。 找到这这个服务务程序的的虚拟目目录,右右键,选选择“属性”。找到“目目录安全全性”选项卡卡。编辑辑“匿名访访问和验验证控制制”。 取消消“匿名访访问”和“集成WWinddowss验证”,选择择“基本验验证”。 好了,现现在如果果再想打打开这个个程序,就就会提示示用户名名和密码码,而这这个权力力是在服服务器上上设置的的。 现在我我们来做做一个客客户程序序,这是是一个普普通的WWinddowss程序。添加Weeb引用用。 在输入入Webb Seerviice的的地址以以后,它它就会提提示你输输入用户户名和密密码,如如果不对对,你是是没有办办法调用用这个WWeb服服务的。 在输入入服务器器正确的的用户名名和密码码以后,你你就可以以使用了了。 现在做做一个BButtton来来调用远远程的方方法。PubllicCClasss FFormm1Inheeritts SSysttem.Winndowws.FFormms.FFormmDim a AAsNeew llocaalhoost.Serrvicce2()PrivvateeSubb Foorm11_Looad(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddlessMyBBasee.LooadEndSSubPrivvateeSubb Buuttoon1_Cliick(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddless Buuttoon1.CliickTry MMsgBBox(a.HHellloWoorldd)Catcch MMsgBBox("请求求失败"")EndTTryEndSSubEndCClasss你会发现现,运行行以后将将提示你你“运行失失败”,这就就是说,调调用这个个方法的的时候,还还要发送送这个服服务器的的用户名名和密码码上去。我们可以以采用这这个方法法来解决决:PrivvateeSubb Foorm11_Looad(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddlessMyBBasee.Looad'a.CCreddenttialls获取取或设置置Webb服务客客户端身身份验证证的安全全凭据'Sysstemm.Neet.NNetwworkkCreedenntiaal为基基于密码码的验证证方案提提供凭据据 a.Creedenntiaals = NNew Sysstemm.Neet.NNetwworkkCreedenntiaal(""Admminiistrratoor", """)EndSSub 好了,现现在能正正常工作作了。C#代码码:usser1107.Serrvicce1 objj=neew uuserr1077.Seerviice11();privvateevoiid bbuttton11_Cllickk(obbjecct ssendder, Syysteem.EEvenntArrgs e)laabell1.TTextt=obbj.HHellloWoorldd();privvateevoiid FFormm1_LLoadd(obbjecct ssendder, Syysteem.EEvenntArrgs e) objj.Crredeentiialss = neww Syysteem.NNet.NettworrkCrredeentiial("Addminnisttrattor"", ""useer1007"); 利用这这个方式式,可以以杜绝没没有权限限的用户户调用WWeb服服务。二、使用用 Sooap 标头自自定义身身份验证证和授权权 在 Innterrnett 上,您您可能需需要对 SQLL 数据据库执行行自定义义身份验验证和授授权。在在这种情情况中,应应向服务务传递自自定义凭凭据(如如用户名名和密码码),并并让服务务自己处处理身份份验证和和授权。 将额外的的信息连连同请求求一起传传递给 XMLL Weeb 服服务的简简便方法法是通过过 SOOAP 标头。为为此,需需要在服服务中定定义一个个从 SSOAPPHeaaderr 派生生的类,然然后将服服务的公公共字段段声明为为该类型型。下面我们们通过一一个例子子来说明明这个问问题。首先做一一个Weeb服务务程序。在这个程程序里面面,需要要注意:服务中中的每个个 WeebMeethood 都都可以使使用 SSoappHeaaderr 自定定义属性性定义一一组关联联的标头头。默认情况况下,标标头是必必需的,但但也可以以定义可可选标头头。SooapHHeadder 属性指指定公共共字段的的名称或或者 CClieent 或 SServver 类的属属性(本本标题中中称为 Heaaderrs 属属性)。在为输入入标头调调用方法法前,WWebSServvicee 设置置 Heeadeers 属性的的值;而而当方法法为输出出标头返返回时,WWebSServvicee 检索索该值。我们可以以先做一一个标头头类:PubllicCClasss AAuthhHeaaderrVB : IInheeritts SSoappHeaaderr它继承于于SoaapHeeadeer,然然后把它它声明成成一个对对象:Publlic sHeeadeer AAs AAuthhHeaaderrVB然后,所所有需要要标头控控制的方方法,都都需要在在前缀上上加上标标头声明明:<WebbMetthodd(), SooapHHeadder("sHHeadder"")> PubbliccFunnctiion SeccureeMetthodd() AsSttrinng下面是具具体的程程序,当当然为了了简单,得得到客户户传过来来的用户户名和密密码以后后,我们们并不是是用数据据库处理理,而是是简单的的用一个个IF语语句处理理,但是是这种方方法,可可以扩大大成各种种情况:Impoortss Syysteem.WWeb.SerrviccesImpoortss Syysteem.WWeb.Serrvicces.Prootoccolss<WebbSerrvicce(NNameespaace:="hhttpp:/temmpurri.oorg/")>> _PubllicCClasss SServvicee1Inheeritts SSysttem.Webb.Seerviicess.WeebSeerviicePubllicCClasss AAuthhHeaaderrVB : Innherritss SooapHHeadderPubllic Useernaame AsSttrinngPubllic Passswoord AsSttrinngEndCClasssPubllic sHeeadeer AAs AAuthhHeaaderrVB <WeebMeethood(), SSoappHeaaderr("ssHeaaderr")>> PuubliicFuuncttionn SeecurreMeethood() AssStrringgIf (sHeeadeer IIsNoothiing) ThhenRetuurn "错误误: 请提提供凭据据"EndIIfDim usrr AssStrringg = sHeeadeer.UUserrnammeDim pwdd AssStrringg = sHeeadeer.PPasssworrdIf (AutthennticcateeUseer(uusr, pwwd) ThhenRetuurn "成功功: "" & usrr & ","" & pwddElseeRetuurn "错误误: 未能能通过身身份验证证"EndIIfEndFFuncctioon <WeebMeethood(), SSoappHeaaderr("ssHeaaderr")>> PuubliicFuuncttionn HeellooWorrld() AAsSttrinngIf (sHeeadeer IIsNoothiing) ThhenRetuurn "错误误: 请提提供凭据据"EndIIfDim usrr AssStrringg = sHeeadeer.UUserrnammeDim pwdd AssStrringg = sHeeadeer.PPasssworrdIf (AutthennticcateeUseer(uusr, pwwd) ThhenRetuurn "成功功: "" & "你好好,我的的世界""ElseeRetuurn "错误误: 未能能通过身身份验证证"EndIIfEndFFuncctioonPrivvateeFunnctiion AutthennticcateeUseer(BByVaal uusr AsSttrinng, ByyVall pwwd AAsSttrinng) AsBoooleeanIf (Nott (uusr IsNoothiing) AnndNoot (pwdd IssNotthinng) Thhen' 可在在此查询询数据库库以获取取凭据.If uusr = ""abcc" AAnd pwdd = "1223" TheenRetuurnTTrueeEndIIfEndIIfRetuurnFFalsseEndFFuncctioonEndCClasss 运行一一下,我我们可以以看到提提供方法法说明的的网站。 但是这这里已经经不提供供测试,而而是提供供了用户户名和密密码的加加入的说说明。POSTT /WWebSServvicee1/SServvicee1.aasmxx HTTTP/1.11Hostt: llocaalhoostConttentt-Tyype: teext/xmll; ccharrsett=uttf-88Conttentt-Leengtth: lenngthhSOAPPActtionn: ""htttp:/teempuuri.orgg/HeellooWorrld""<?xmml vverssionn="11.0"" enncoddingg="uutf-8"?><soaap:EEnveeloppe xxmlnns:xxsi="htttp:/wwww.w3.orgg/20001/XMLLSchhemaa-innstaancee" xxmlnns:xxsd="htttp:/wwww.w3.orgg/20001/XMLLSchhemaa" xxmlnns:ssoapp="hhttpp:/schhemaas.xxmlssoapp.orrg/ssoapp/ennvellopee/">> <ssoapp:Heeadeer> <AuuthHHeadderVVB xxmlnns=""htttp:/teempuuri.orgg/">> <<Useernaame>>strringg</UUserrnamme> <<Passswoord>>strringg</PPasssworrd> </AAuthhHeaaderrVB>> </soaap:HHeadder>> <ssoapp:Boody>> <HeellooWorrld xmllns="htttp:/ttemppurii.orrg/"" />> </soaap:BBodyy></sooap:Envveloope>>现在我们们来做一一个客户户程序,看看看SOOAP标标头到底底有什么么样的表表现。为了进行行测试,我我们简单单的加三三个Buuttoon。分分别用不不同的情情况调用用Webb服务的的方法。添加Weeb引用用。代码,第第一个事事件密码码有意给给的是错错的。PubllicCClasss FFormm1Inheeritts SSysttem.Winndowws.FFormms.FFormmDim a AAsNeew llocaalhoost.Serrvicce1()'调用SSecuureMMethhodPrivvateeSubb Buuttoon1_Cliick(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddless Buuttoon1.CliickDim myHHeadder AsNeew llocaalhoost.AutthHeeadeerVBB() myyHeaaderr.Ussernnamee = "abbc" myyHeaaderr.Paasswwordd = "12234"" a.AutthHeeadeerVBBVallue = mmyHeeadeer MssgBoox(aa.SeecurreMeethood()EndSSub'调用HHellloWoorlddPrivvateeSubb Buuttoon2_Cliick(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddless Buuttoon2.CliickDim myHHeadder AsNeew llocaalhoost.AutthHeeadeerVBB() myyHeaaderr.Ussernnamee = "abbc" myyHeaaderr.Paasswwordd = "1223" a.AutthHeeadeerVBBVallue = mmyHeeadeer MssgBoox(aa.HeellooWorrld)EndSSub'直接调调用HeellooWorrldPrivvateeSubb Buuttoon3_Cliick(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddless Buuttoon3.CliickTry MMsgBBox(a.HHellloWoorldd)Catcch eee AAs EExceeptiion MMsgBBox(ee.Messsagge)EndTTryEndSSubPrivvateeSubb Foorm11_Looad(ByVVal sennderr Ass Syysteem.OObjeect, ByyVall e As SSysttem.EveentAArgss) HHanddlessMyBBasee.LooadEndSSubEndCClasss下面我们们来做个个实验首先点:“直接调调用HeellooWorrld”它会提示示你“进行调调用以前前,客户户端没有有设置SSOAPP标头”,所以以直接调调用是不不可以的的。下面,你你点一下下“调用SSecuureMMethhod”,而程程序中有有意把提提供的密密码设成成错误的的。问题是你你再点一一下“直接调调用HeellooWorrld”,它也也提供了了一个密密码错误误的信息息。说明明标头的的设置对对第二个个方法也也是起作作用的。好,现在在你点一一下“调用HHellloWoorldd”,这段段程序的的用户名名和密码码是正确确的,成成功了。现在,你你再点一一下“直接调调用HeellooWorrld”,它将将出来一一个正确确的结果果,说明明只要标标头正确确,你就就可以一一直的使使用。如果再设设置一下下错误的的标头呢呢?现在点它它又是错错误,可可以看出出来,一一个Weeb服务务程序,标标头只有有一个。利用这个个原理,我我们就可可以设计计出很好好的具有有安全性性的程序序来。同样的CC#代码码:服务器:usinng SSysttem.Webb.Seerviicess.Prrotoocolls;publliccclasss AAuthhHeaaderrVB :SooapHHeadderpubllicsstriing Useernaame;publlicsstriing Passswoord;publlic AutthHeeadeerVBB sHHeadder;WWebMMethhod(), SoaapHeeadeer(""sHeeadeer")publlicsstriing SeccureeMetthodd()if (sHeeadeer=nulll) retuurn "错误误: 请提提供凭据据"striing usrr= ssHeaaderr.Ussernnamee;striing pwdd = sHeeadeer.PPasssworrd;if (AutthennticcateeUseer(uusr, pwwd)retuurn "成功功: "" + usrr + ","" + pwdd;elseeretuurn "错误误: 未能能通过身身份验证证"WWebMMethhod(), SoaapHeeadeer(""sHeeadeer")publlicsstriing HellloWWorlld()if (sHeeadeer=nulll)retuurn "错误误: 请提提供凭据据"striing usrr= ssHeaaderr.Ussernnamee;striing pwdd= ssHeaaderr.Paasswwordd;if (AutthennticcateeUseer(uusr, pwwd)retuurn "成功功: "" + "你好好,我的的世界""elseeretuurn "错误误: 未能能通过身身份验证证"booll AuutheentiicatteUsser(strringg ussr, strringg pwwd)if (ussr!=nulll) && (pwwd !=nuull)/可在在此查询询数据库库以获取取凭据.if (ussr = ""abcc") && (pwwd = ""1233")retuurnttruee;retuurnffalsse;客户端 loccalhhostt.Seerviice11 a=neww loocallhosst.SServvicee1();privvateevoiid bbuttton11_Cllickk(obbjecct ssendder, Syysteem.EEvenntArrgs e)llocaalhoost.AutthHeeadeerVBB myyHeaaderr=neew llocaalhoost.AutthHeeadeerVBB(); mmyHeeadeer.UUserrnamme = "aabc"" mmyHeeadeer.PPasssworrd = "112344" aa.AuuthHHeadderVVBVaaluee = myHHeadder; MMesssageeBoxx.Shhow(a.SSecuureMMethhod();privvateevoiid bbuttton22_Cllickk(obbjecct ssendder, Syysteem.EEvenntArrgs e)llocaalhoost.AutthHeeadeerVBB myyHeaaderr=neew llocaalhoost.AutthHeeadeerVBB(); mmyHeeadeer.UUserrnamme = "aabc"" mmyHeeadeer.PPasssworrd = "1123"" aa.AuuthHHeadderVVBVaaluee = myHHeadder; MMesssageeBoxx.Shhow(a.HHellloWoorldd(); privvateevoiid bbuttton33_Cllickk(obbjecct ssendder, Syysteem.EEvenntArrgs e) MeessaageBBox.Shoow(aa.HeellooWorrld();