使用SoapHeader传递Web Serivices自定义的身份验证数据

在调用 Web Serivices , 往往需要身份验证 , 使得通过验证的用户才能调用你 Web Serivices 中的方法 . 当然你可以通过将参数添加到每个需要自定义身份验证方案的 Web services 方法中去 , 这需要花费很大的精力 .IssueVision 中使用了非常常用而且有效便捷的方法 ----- 使用 SoapHeader 来实现自定义身份验证数据的传递 .
    
SoapHeader 提供了一种方法,用于将数据传递到 Web services 方法或从 Web services 方法传递数据,条件是该数据不直接与 Web services 方法的主功能相关 . 你不用将参数添加到每个需要自定义身份验证方案的 Web services 方法,而可以将引用从 SoapHeader 派生的类的 SoapHeaderAttribute 应用于每个 Web services 方法。从 SoapHeader 派生的类的实现处理该自定义身份验证方案 . IssueVision 就是利用 SoapHeader 的这种能力来实现自定义身份验证数据传递的 .

    
我们来看一下如何利用 SoapHeader 来传递数据 .
     1 . 首先需要在服务中定义一个从 SOAPHeader 派生的类 , 表示传入 SOAP 标头的数据 .
    IssueVision
在中 IssueVisionWeb 项目 ( 此项目用于发布 Web Services) 中通过创建 CredentialSoapHeader 类来实现第一步 .

CredentialSoapHeader.cs
using System.Web.Services.Protocols;
namespace IssueVision.Web
{
 public class CredentialSoapHeader : SoapHeader
 {
  private string m_username;
  private string m_password;
  public string Username
  {
   get{ return m_username;}
   set{ m_username = value;}
  }
  public string Password
  {
   get{ return m_password;}
   set{ m_password = value;}
  }
 }
}



























  
2 . 将服务的公共字段声明为该类型 , 使该 SoapHeader Web Services 的公共合同中公开 , 并在创建代理时可由客户端使用 .

    IssueVision
Web Services----IssueVisionServices.asmx 如此实现 .

IssueVisionServices.asmx
代码片断 :

public class IssueVisionServices : WebService
 {
  ...
  private CredentialSoapHeader m_credentials;
  // custom SOAP header to pass credentials
  public CredentialSoapHeader Credentials
  {
     get { return m_credentials; }
     set { m_credentials = value; }
  }
  .......
}

   
3 . Web Services 使用 SoapHeader 自定义属性定义一组关联的标头 , 服务中的每个 WebMethod 都可以使用 .( 默认情况下,标头是必需的,但也可以定义可选标头 )

    IssueVisionServices.asmx
代码片断 :

  ....
  [WebMethod(Description="Returns the lookup tables for IssueVision.")]
  [SoapHeader("Credentials")]
  public IVDataSet GetLookupTables()
  {
   SecurityHelper.
VerifyCredentials (this);   
   return new IVData().GetLookupTables();
  }

    SecurityHelper
类的 VerifyCredentials 方法用来从 Web Services 中的 SoapHeader 类来得到自定义身份验证凭据 ( 如用户名和密码 ).

  SecurityHelper.cs
代码片断如下 :

// verifies the clients credentials
  public static void VerifyCredentials(IssueVisionServices
service )
  {
   if (service.Credentials == null || service.Credentials.Username == null || service.Credentials.Password == null )   //
如果没有认证信息 , 返回 SoapException, 这样就不能匿名调用 Web Method
   {
    EventLogHelper.LogFailureAudit("A login was attempted with missing credential information.");
    throw new SoapException(string.Empty, SoapException.ClientFaultCode, "Security");
   }
   string password = Authenticate( service .Credentials) ;
  }
  // authenticates a user's credentials passed in a custom SOAP header
  private static string Authenticate( CredentialSoapHeader
header )
  {
   DataSet dataSet = new DataSet();
   string dbPasswordHash;
   try
   {
    SqlConnection conn = new SqlConnection(Common.ConnectionString);
    SqlCommand cmd = new SqlCommand("GetUser", conn);
    cmd.Parameters.Add("@UserName",
header .Username );
    cmd.CommandType = CommandType.StoredProcedure;
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    da.Fill(dataSet);
   }
   catch (Exception ex)
   {
    EventLogHelper.LogFailureAudit(string.Format("The GetUser stored procedure encounted a problem: {0}", ex.ToString()));
    throw new SoapException(string.Empty, SoapException.ServerFaultCode, "Database");
   }
   
   // does the user exist?
   if (dataSet.Tables[0].Rows.Count == 0)
   {
    EventLogHelper.LogFailureAudit(string.Format("The username {0} does not exist.", header.Username));
    throw new SoapException(string.Empty, SoapException.ClientFaultCode, "Security");
   }
   else
   {
    // we found the user, verify the password hash by compare the Salt + PasswordHash
    DataRow dataRow = dataSet.Tables[0].Rows[0];
    dbPasswordHash = (string)dataRow["PasswordHash"];
    string dbPasswordSalt = (string)dataRow["PasswordSalt"];
    // create a hash based on the user's salt and the input password
    string passwordHash = HashString(dbPasswordSalt + header.Password);
    // does the computed hash match the database hash?
    if (string.Compare(dbPasswordHash, passwordHash) != 0)
    {
     EventLogHelper.LogFailureAudit(string.Format("The password for the username {0} was incorrect.", header.Username));
     throw new SoapException(string.Empty, SoapException.ClientFaultCode, "Security");
    }
   }
   
   return dbPasswordHash;
}

 
4 . 最后客户端在调用要求标头的方法之前,需直接在代理类上设置标头 .

  IssueVision
SmartClient 端的 WebServicesLayer 类来调用此 Web Services

  WebServicesLayer.cs
程序片断如下 :

private static IssueVisionServices GetWebServiceReference(string username, string password)
  {
   IssueVisionServices dataService = new IssueVisionServices();
   
   //<ReplaceWithWse>
   
CredentialSoapHeader header = new CredentialSoapHeader();
   header.Username = username;
   header.Password = password;
   dataService.CredentialSoapHeaderValue = header;
   //</ReplaceWithWse>
   
   InitWebServiceProxy(dataService);
   
   return dataService;
}

  
通过以上步骤就可以完成 Web Services 自定义身份验证了 .IssueVision 中还有很多相关的操作 , 因为在这里只是讨论一下 SoapHeader 的用法 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值