你的位置:首页 > ASP.net教程

[ASP.net教程]关于WEB ServiceWCFWebApi实现身份验证之WEB Service篇


在这个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", Get

辅助方法定义如下:

    private 

这里说明一下,不论是采用服务引用还是动态调用服务,均需确保引用同一个COOKIE容器,而且在动态调用服务时,还需注意最终返回的结果为

//这里是得到的

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方法 

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