WebService登陆验证四种方式

在这个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" οnclick="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" οnclick="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" 
            οnclick="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;
        }
    }

转载于:https://www.cnblogs.com/saodiseng2015/p/9270514.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于物联网技术的交通信号控制系统的设计与实现可以使用以下技术栈: 1. 物联网通信技术:使用物联网通信技术,如MQTT(Message Queuing Telemetry Transport)、CoAP(Constrained Application Protocol)等,实现数据的传输和通信。这些通信协议可以在设备之间进行可靠的数据传输和远程控制。 2. 传感器技术:使用各种传感器技术来感知交通状况,如摄像头、雷达、车载设备等。这些传感器可以采集交通数据,如交通流信息、车辆数量、行驶速度等,用于后续的数据处理和分析。 3. 数据处理与分析技术:利用大数据处理和分析技术,对采集到的交通数据进行实时处理和分析。可以使用机器学习、数据挖掘等算法,提取交通流特征、预测交通状况,并生成最优的信号控制策略。 4. 决策与控制技术:根据数据处理和分析的结果,自动化地进行决策,并生成信号控制指令。可以使用优化算法、模型预测控制等技术,动态调整信号灯的时序,以优化交通流的通过效率。 5. 前端开发技术:设计用户界面,用于显示实时交通信息、调整系统参数和监控系统运行状态等。可以使用前端开发技术,如HTML、CSS、JavaScript等,实现友好的用户界面和交互效果。 6. 后端开发技术:搭建系统的后端服务,处理数据传输、数据存储和业务逻辑等。可以使用后端开发技术,如Python、Java、Node.js等,实现系统的功能和服务。 7. 数据库技术:用于存储和管理交通数据、系统配置信息等。可以使用关系型数据库(如MySQL、PostgreSQL)或非关系型数据库(如MongoDB、Redis)来存储和查询数据。 8. 云计算技术:利用云计算平台,如Amazon Web Services(AWS)、Microsoft Azure等,实现系统的弹性扩展、高可用性和数据安全性。 这些技术栈是基于物联网技术的交通信号控制系统设计与实现中常见的技术组合。根据具体的需求和项目情况,可以选择适合的技术栈来搭建系统,并实现交通信号的智能控制和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值