分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

WebService登陆验证四种方式

发布时间:2023-09-06 02:02责任编辑:熊小新关键词:Web

在这个WEB API横行的时代,讲WEB Service技术却实显得有些过时了,过时的技术并不代表无用武之地,有些地方也还是可以继续用他的,我之所以会讲解WEB Service,源于我最近面试时被问到相关问题,我这里只是重新复习一下并总结一下,给新手们指指路,大牛们可以无视之,当然不足之处还请大家指教,谢谢!

WEB Service身份验证,网上已有许多的相关文章,总结起来有:基于自定义SoapHeader验证、Form验证、集成Windows身份验证、服务方法加入一个或几个验证参数;下面就不废话了,直接分享实现的代码吧,中间有涉及注意的地方,我会有说明文字的。

1.基于自定义SoapHeader验证

定义服务:(注意UserValidationSoapHeader必需有无参构造函数,否则无法序列化)

//UserValidationSoapHeader: ???public class UserValidationSoapHeader : SoapHeader ???{ ???????public string UserName { get; set; } ???????public string Password { get; set; } ???????public UserValidationSoapHeader() ???????{ } ???????public bool IsValid() ???????{ ???????????if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(Password)) ???????????{ ???????????????throw new Exception("用户名及密码不能为空!"); ???????????} ???????????if (!string.Equals(UserName, "admin") || !string.Equals(Password, "123456")) ???????????{ ???????????????throw new Exception("用户名或密码不正确!"); ???????????} ???????????return true; ???????} ???}//SoapHeaderWebService: ???[WebService(Namespace = "http://www.zuowenjun.cn")] ???[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] ???[System.ComponentModel.ToolboxItem(false)] ???// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 ???[System.Web.Script.Services.ScriptService] ???public class SoapHeaderWebService : System.Web.Services.WebService ???{ ???????public UserValidationSoapHeader userValidation; ???????[WebMethod(Description="问候")] ???????[SoapHeader("userValidation")] ???????public string HelloTo(string name) ???????{ ???????????if (userValidation.IsValid() && !string.IsNullOrEmpty(name)) ???????????{ ???????????????return "Hello " + name; ???????????} ???????????return "Hello World!"; ???????} ???}

客户端先通过服务地址引用服务,服务引用有两种,分为服务引用和WEB服务引用(后面涉及到服务引用的不再重述)

服务引用:(这里是按照WCF的模式来生成WEB服务代理类)

WEB服务引用:

    

(如果通过项目右键,则可以直接点击“添加WEB引用”到此画面)

客户端使用如下:

 ???????private void CallWebServiceFromWebReference() ???????{ ???????????try ???????????{ ???????????????var svc = new RefWebSoapHeaderWebService.SoapHeaderWebService(); ???????????????svc.UserValidationSoapHeaderValue = new RefWebSoapHeaderWebService.UserValidationSoapHeader() { UserName = "admin", Password = "123456" }; ???????????????string result = svc.HelloTo(TextBox1.Text); ???????????????Label1.Text = result; ???????????} ???????????catch (Exception ex) ???????????{ ???????????????Label1.Text = ex.Message; ???????????} ???????} ???????private void CallWebServiceFromServiceReference() ???????{ ???????????try ???????????{ ???????????????var svc = new RefSoapHeaderWebService.SoapHeaderWebServiceSoapClient(); ???????????????var header = new RefSoapHeaderWebService.UserValidationSoapHeader(); ???????????????header.UserName = "admin"; ???????????????header.Password = "123456"; ???????????????string result = svc.HelloTo(header, TextBox1.Text); ???????????????Label1.Text = result; ???????????} ???????????catch (Exception ex) ???????????{ ???????????????Label1.Text = ex.Message; ???????????} ???????} ???????protected void Button1_Click(object sender, EventArgs e) ???????{ ???????????if (RadioButtonList1.SelectedValue == "1") ???????????{ ???????????????CallWebServiceFromServiceReference(); ???????????} ???????????else ???????????{ ???????????????CallWebServiceFromWebReference(); ???????????} ???????}

上述代码我针对两种WEB服务引用作了不同的使用实例,关键看方法调用,服务引用下生成的服务方法参数中会自动加入一个soapHeader的参数,而WEB服务引用则没有,我感觉采用WEB服务引用基于这种验证比较方便,因为只需将soapHeader实例赋值一次就可以多次调用不同的服务方法。

2.Form验证

定义服务:

//专门用于登录的WEB服务: ???[WebService(Namespace = "http://www.zuowenjun.cn")] ???[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] ???[System.ComponentModel.ToolboxItem(false)] ???// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 ???[System.Web.Script.Services.ScriptService] ???public class FormAuthWebService : System.Web.Services.WebService ???{ ???????[WebMethod] ???????public bool Login(string username, string password) ???????{ ???????????return UserBusiness.Login(username, password); ???????} ???}//正常的WEB服务: ???[WebService(Namespace = "http://www.zuowenjun.cn")] ???[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] ???[System.ComponentModel.ToolboxItem(false)] ???// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 ???[System.Web.Script.Services.ScriptService] ???public class FormAuthHelloWebService : System.Web.Services.WebService ???{ ???????[WebMethod] ???????public string HelloTo(string name) ???????{ ???????????if (!string.IsNullOrEmpty(name)) ???????????{ ???????????????return "Hello " + name; ???????????} ???????????return "Hello World"; ???????} ???????[WebMethod] ???????public void Logout() ???????{ ???????????UserBusiness.Logout(); ???????} ???}//业务辅助类: ???public static class UserBusiness ???{ ???????public static bool Login(string userName, string password) ???????{ ???????????if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password)) ???????????{ ???????????????throw new Exception("用户名及密码不能为空!"); ???????????} ???????????if (!string.Equals(userName, "admin") || !string.Equals(password, "123456")) ???????????{ ???????????????throw new Exception("用户名或密码不正确!"); ???????????} ???????????SaveLoginStauts(userName); ???????????return true; ???????} ???????public static bool IsAuthenticated() ???????{ ???????????return HttpContext.Current.Request.IsAuthenticated; ???????} ???????public static void Logout() ???????{ ???????????System.Web.Security.FormsAuthentication.SignOut(); ???????} ???????private static void SaveLoginStauts(string userName) ???????{ ???????????System.Web.Security.FormsAuthentication.SetAuthCookie(userName, false); ???????} ???}

从上面的代码可以看出,这里采用了基于ASP.NET FORM验证来保存登录状态,其它代码与正常无异

因为采用了ASP.NET FORM验证,所以web.config需要加入以下配置:

//在system.web节点加入以下配置,因为我将WEB服务全部放到了Services目录下,所以仅对该目录进行了限制 ???<authentication mode="Forms"> ?????<forms name="auth.webservice" loginUrl="~/Services/FormAuthWebService.asmx/Login"> ?????</forms> ???</authentication> ???<webServices> ?????<protocols> ???????<add name="HttpSoap"/> ???????<add name="HttpPost"/> ???????<add name="HttpGet"/> ???????<add name="Documentation"/> ?????</protocols> ???</webServices> ?</system.web> ?<location path="Services"> ???<system.web> ?????<authorization> ???????<deny users="?"/> ?????</authorization> ???</system.web> ?</location>

注意以下2点:

1.上面loginUrl="~/Services/FormAuthWebService.asmx/Login",这里我直接将未登录直接转到Login,原因是如果不加Login,那么你将无法在WEB浏览器上进行登录调试及其它服务方法的调试。

2.由于采用了FORM验证,且禁止匿名访问,造成无法正常引用服务,原因是服务引用也是一次HTTP请求,默认是未登录的情况,你去引用受限的服务地址,它就会自动跳转到登录的服务地址,所以针对这个问题,我采用了两种办法,第一种是:先不要禁止匿名访问,当服务引用成功后,再加上该配置,第二种是:不直接引用服务,采用代码动态请求服务方法来进行相关的调用,客户端使用代码如下:

//第一种:采用服务引用: ???????protected void Button2_Click(object sender, EventArgs e) ???????{ ???????????try ???????????{ ???????????????CookieContainer cookieContainer = new CookieContainer(); ???????????????var svc = new RefFormAuthLoginWebService.FormAuthWebService(); ???????????????svc.CookieContainer = cookieContainer; //共享cookie容器 ???????????????if (svc.Login("admin", "123456")) ???????????????{ ???????????????????var svc2 = new RefFormAuthWebService.FormAuthHelloWebService(); ???????????????????svc2.CookieContainer = cookieContainer;//共享cookie容器 ???????????????????Label2.Text = svc2.HelloTo(TextBox2.Text); ???????????????} ???????????} ???????????catch (Exception ex) ???????????{ ???????????????Label2.Text = ex.Message; ???????????} ???????}//第二种:采用动态请求调用: ???????protected void Button2_Click(object sender, EventArgs e) ???????{ ???????????try ???????????{ ???????????????CookieContainer cookieContainer = new CookieContainer(); ???????????????var result = CallWebServiceFromHttpWebRequest("FormAuthWebService.asmx/Login", "username=admin&password=123456", cookieContainer); ???????????????Label2.Text = result.SelectSingleNode("//ns:boolean", GetXmlNamespaceManager(result.NameTable)).InnerText; ???????????????var result2 = CallWebServiceFromHttpWebRequest("FormAuthHelloWebService.asmx/HelloTo", "name=" + HttpUtility.UrlEncode(TextBox2.Text, Encoding.UTF8), cookieContainer); ???????????????Label2.Text = result2.SelectSingleNode("//ns:string", GetXmlNamespaceManager(result2.NameTable)).InnerText; ???????????catch (Exception ex) ???????????{ ???????????????Label2.Text = ex.Message; ???????????}

辅助方法定义如下:

 ???????private XmlDocument CallWebServiceFromHttpWebRequest(string serviceUrl,string serviceParams,CookieContainer cookieContainer) ???????{ ???????????HttpWebRequest request =(HttpWebRequest)WebRequest.Create("http://localhost:8768/Services/" + serviceUrl); ???????????request.Method = "POST"; ???????????request.ContentType = "application/x-www-form-urlencoded"; ???????????request.Credentials = CredentialCache.DefaultCredentials; ???????????byte[] data = Encoding.UTF8.GetBytes(serviceParams);//参数 ???????????request.ContentLength = data.Length; ???????????request.CookieContainer = cookieContainer; //共享cookie容器 ???????????Stream writer = request.GetRequestStream(); ???????????writer.Write(data, 0, data.Length); ???????????writer.Close(); ???????????WebResponse response = request.GetResponse(); ???????????StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); ???????????String retXml =sr.ReadToEnd(); ???????????sr.Close(); ???????????XmlDocument doc = new XmlDocument(); ???????????doc.LoadXml(retXml); ???????????return doc; ???????} ???????private XmlNamespaceManager GetXmlNamespaceManager(XmlNameTable table) ???????{ ???????????XmlNamespaceManager nsMgr = new XmlNamespaceManager(table); ???????????nsMgr.AddNamespace("ns", "http://www.zuowenjun.cn"); ???????????return nsMgr; ???????}

这里说明一下,不论是采用服务引用还是动态调用服务,均需确保引用同一个COOKIE容器,而且在动态调用服务时,还需注意最终返回的结果为XML,需要进行相应的解析才能得到指定的值,相关的注意事项,可参见这篇文章《C#操作xml SelectNodes,SelectSingleNode总是返回NULL 与 xPath 介绍》,其实看了过后就知道是XML命名空间的问题,也可以去掉命名空间,这样解析就方便多了,如下代码:

//这里是得到的XML,调用去除命名空间的方法: String retXml = RemoveNamespace(sr.ReadToEnd());private string RemoveNamespace(string xml) ???????{ ???????????var reg = new System.Text.RegularExpressions.Regex("xmlns=\".*\"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); ???????????return reg.Replace(xml, ""); ???????}protected void Button2_Click(object sender, EventArgs e){... ???????????????var result = CallWebServiceFromHttpWebRequest("FormAuthWebService.asmx/Login", "username=admin&password=123456", cookieContainer); ???????????????Label2.Text = result.SelectSingleNode("//boolean").InnerText; ???????????????var result2 = CallWebServiceFromHttpWebRequest("FormAuthHelloWebService.asmx/HelloTo", "name=" + HttpUtility.UrlEncode(TextBox2.Text, Encoding.UTF8), cookieContainer); ???????????????Label2.Text = result2.SelectSingleNode("//string").InnerText;...}

3.集成Windows身份验证,这个很简单,首先将IIS设置成集成WINDOWS身份验证,服务定义无特殊代码

客户端使用如下:

Test.WebReference.Service1 service= new Test.WebReference.Service1(); //生成web service实例 ??service.Credentials = new NetworkCredential("user","123456"); //user是用户名,该用户需要有一定的权限 ??lblTest.Text =service.HelloTo("zuowenjun") ; //调用web service方法 ?

WEB页面示例代码:

 ???<form id="form1" runat="server"> ???<fieldset> ???<legend>基于自定义SoapHeader验证后调用服务</legend> ???<div> ???????<asp:RadioButtonList ID="RadioButtonList1" runat="server" RepeatDirection="Horizontal"> ???????<asp:ListItem Value="1">From Service Reference</asp:ListItem> ???????<asp:ListItem Value="2">From Web Reference</asp:ListItem> ???????</asp:RadioButtonList> ???????<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> ???????<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /> ???????<br /> ???????<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> ???</div> ???</fieldset> ???<p> ??????? </p> ???<p> ??????? </p> ???<p> ??????? </p> ????<fieldset> ???<legend>基于自定义Form身份验证后调用服务</legend> ???<div> ???????<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> ???????<asp:Button ID="Button2" runat="server" onclick="Button2_Click" Text="Button" /> ???????<br /> ???????<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label> ???</div> ???</fieldset> ??<p> ??????? </p> ???<p> ??????? </p> ???<p> ??????? </p> ????<fieldset> ???<legend>基于自定义Windows验证后调用服务</legend> ???<div> ???????<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox> ???????<asp:Button ID="Button3" runat="server" ?Text="Button" ????????????onclick="Button3_Click" /> ???????<br /> ???????<asp:Label ID="Label3" runat="server" Text="Label"></asp:Label> ???</div> ???</fieldset> ???</form>

最终呈现效果截图如下:

 
由于下班时间写的,所以有些仓促,不足之处,敬请指出,谢谢!~v~

补充知识点:

我上面的代码在验证用户登录时,若验证不通过,我是直接抛出一个Exception,WEB服务在返回到客户端前会被包装为SoapException类型的异常,这样导至在客户端无法很直接的查看错误内容,所以这里可以采用这篇文章《封装SoapException处理Webservice异常》里面的方法来添加格式化SoapException的方法及解析SoapException的方法。

关于WEB SERIVCE在多个ASP.NET页面中使用时共享COOKIE的办法,实现代码如下:

首先正常引用WEB服务,然后自定义继承自该引用的服务类,并在其构造函数中实例化CookieContainer并保存到静态字段中;

使用的时,不要调用引用的服务,而应该调用这些自定义的子类,从而实现共享COOKIE

 ???public class FormAuthHelloWebServiceEx : RefFormAuthWebService.FormAuthHelloWebService ???{ ???????private static CookieContainer cookieContainer; ???????static FormAuthHelloWebServiceEx() ???????{ ???????????cookieContainer = new System.Net.CookieContainer(); ???????} ???????public FormAuthHelloWebServiceEx(CookieContainer ckContainer) ???????{ ???????????if (cookieContainer != null) ???????????{ ???????????????cookieContainer = ckContainer; ???????????} ???????????this.CookieContainer = cookieContainer; ???????} ???} ???public class FormAuthWebServiceEx : RefFormAuthLoginWebService.FormAuthWebService ???{ ???????private static CookieContainer cookieContainer; ???????static FormAuthWebServiceEx() ???????{ ???????????cookieContainer = new System.Net.CookieContainer(); ???????} ???????public FormAuthWebServiceEx(CookieContainer ckContainer) ???????{ ???????????if (cookieContainer != null) ???????????{ ???????????????cookieContainer = ckContainer; ???????????} ???????????this.CookieContainer = cookieContainer; ???????} ???}

WebService登陆验证四种方式

原文地址:https://www.cnblogs.com/ztb123/p/9270514.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved