用WSE在Web服务中验证用户身份(2)

6 篇文章 0 订阅
3 篇文章 0 订阅
五、IPasswordProvider接口

WSE定义了一个 Microsoft.Web.Services.Security.IPasswordProvider接口类,我们必须实现这个类来注册一个密码提供者。这个接口有一个方法GetPassword,它接收一个 Microsoft.Web.Services.Security.UsernameToken作为输入参数,该方法返回指定用户的密码。其思想是你可以使用任何你想用的机制保存有效的用户名/密码对,然后提供了一个实现IPasswordProvider接口的类,来让WSE访问你的特定密码存储机制。你甚至可以执行你自己的UsernameToken的摘要(Digest)和散列(Hash)的组合,甚至使用一个共享的密码,以进一步控制你的认证基础结构。

为了把你特定的Password Provider(密码提供者)告诉WSE,你必须配置合适的WSE设置。首先要添加一个Microsoft.Web.Services元素到应用程序的配置文件中的配置元素中。还要指定可以读懂特定配置信息的WSE类。可以把下面的configSections添加到机器上的Machine.config或单独的Web.config中。

<configSections>
<section name="microsoft.web.services"
type="Microsoft.Web.Services.Configuration.WebServicesConfiguration,
Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" />
</configSections>

在本例中,我们将使用Northwind数据库Employees表的一个修改版本来进行查询任务。因为PasswordProvider接口需要返回一个与UsernameToken对象的密码部分匹配的实际密码,所以通常,我们只需要使用WSE加密我们的用户名和密码,然后再通过网络传送给Web服务。

如果你在Solution Explorer中选中你的工程并在其上点击右键,你将看到在底部增加了一个新的菜单“WSE Settings”,你可以在其中设置所有重要的配置和其它使用WSE的配置:

这可让我们很容易的设置Password Provider Implementation(密码提供者实现)元素,Decryption Key Provider Implementation(解密钥提供者)元素,X.509 Certificate(X.509 证书)设置,甚至是我们希望使用的Binary Security Tokens(二进制安全令牌)。此外,其他的选项卡还可以配置用于WSE管道的输入输出过滤器,配置路由,启动诊断功能等等。虽然它不能做我们想做的每件事,但这是WSE易用化的一个良好的开端。

PasswordProvider安全元素是web.config中的<configuration>父元素的一个子元素,它告诉WSE你使用哪个类来实现PasswordProvider接口:

<microsoft.web.services>
 <security>
<!-- NAMESPACE . CLASSNAME , ASSEMBLYNAME -->
<passwordProvider type="WSESecurity.WSEPasswordProvider, WSESecurity" />
 </security>
</microsoft.web.services>

让我们看看在本例中如何实现它:

namespace WSESecurity
{
 public class WSEPasswordProvider : IPasswordProvider
 {
public string GetPassword(UsernameToken token)
{
 try
 {
SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationSettings.
AppSettings["SqlConn"].ToString());
cn.Open();
SqlCommand cmd = new SqlCommand("SELECT Username, password from Employees where 
username ='" + token.Username + "'",cn);
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
dr.Read();
return dr["password"].ToString();
 } 
 catch(Exception ex)
 {
throw new Exception (ex.Message);
 } 
}
 }
}

上面我们给出的代码可以完全实现IPasswordProvider接口,通过用户名/密码来验证一个用户,当然了,还可以把它做得更复杂一些,这请读者们自己去完成。实际上,我们在编程的过程中基本没有写太多用户验证的代码,大部分工作都由WSE暗中处理了。

WebMethod]
public DataSet CustOrderHist(string CustId)
{
 // 只接受 SOAP格式的请求
 SoapContext requestContext = HttpSoapContext.RequestContext;
 if(requestContext==null)
 {
throw new ApplicationException("Non-SOAP request!");
 }
 bool valid=false;
 try
 {
foreach(SecurityToken tkn in requestContext.Security.Tokens)
{
 if(tkn is UsernameToken)
 valid=true; 
} 
 } 
 catch(Exception ex)
 {
throw new Exception( ex.Message + ": " + ex.InnerException.Message);
 } 
 if (valid==false)
throw new ApplicationException("Invalid or Missing Security Token.");
 SqlConnection cn;
 SqlDataAdapter da;
 DataSet ds; 
 cn = new SqlConnection(System.Configuration.ConfigurationSettings.
AppSettings["SqlConn"].ToString());
 cn.Open();
 da = new SqlDataAdapter("custorderHist '" +CustId + "'", cn);
 ds = new DataSet();
 da.Fill(ds, "CustOrderHist");
 return ds;
}

使用上面的WebMethod,我们就可在服务器上实现验证用户名/密码的操作。WebMethod必须引用Microsoft.Web.Services和 Microsoft.Web.Services.Security域名空间。现在,我们要构建一个ASP.NET客户端,这个客户端能够发送验证所需的 SOAP头,并可调用我们的Web服务方法。

七、构建WSE ASP.NET客户端

对于客户端,WSE提供了继承于System.Web.Services.Protocols.SoapHttpClientProtocol类的 Microsoft.Web.Services.WebServicesClientProtocol类。当你在Visual Studio.NET中选择“Add Web Reference”选项的时候,或者使用WSDL.exe程序创建基于WSDL的客户端代码时,你需要使用 SoapHttpClientProtocol类。你可做的就是使用Visual Studio.NET中的“Add Web Reference”选项或者WSDL.exe程序为你的客户端生成代理类,然后把代理类从继承于SoapHttpClientProtocol改为继承于WebServicesClientProtocol。这样代理类就有了RequestSoapContext和 ResponseSoapContext属性,你可以使用它们访问你发送或接收的WS-Security头。在C#工程中,如果你已经使用了“Add Web Reference”选项,你可以点击Solution Explorer中的“Show All Files”按钮,点击这个按钮就可在Solution Explorer的Web References结点中显示Reference.cs文件,让你可以编辑这个文件。

为了创建正确的UsernameToken和在消息级调用Web服务的代理方法,需要使用下面的代码:

private void Button1_Click(object sender, System.EventArgs e)
{ 
 localhost.SecurityServiceWse wse=new localhost.SecurityServiceWse();
 UsernameToken tkn = new UsernameToken(txtUsername.Text,txtPassword.
Text,PasswordOption.SendHashed);
 wse.RequestSoapContext.Security.Tokens.Add (tkn);
 try
 {
DataSet ds=wse.CustOrderHist(txtCustID.Text);
DataGrid1.DataSource=ds;
DataGrid1.DataBind();
 }
 catch(Exception ex)
 {
DataGrid1.Visible=false;
lblMessages.Text=ex.Message;
 }
}

我们要做的就是从客户端的两个文本输入框txtUsername和txtPassword中取得输入字串,然后使用 PasswordOption.SendHashed把它们结合起来创建一个有效的UserNameToken。当调用Web服务时,WSE SOAP扩展验证请求的一般格式,然后核对密码散列并从我们的PasswordProvider方法中取得的密码。如果两者匹配,我们就可调用Web服务方法,客户端返回数据集,显示在一个网格中。

我们现在已经创建了一个完整的使用WSE配合数据库验证SHA1摘要散列用户名/密码的Web服务,希望读者们能通过本文了解到使用WSE保证Web服务安全的基本措施和方法,并能在实际工作中合理的去应用。

在文章的最后,我们给出修改Northwind数据库Employees表的SQL脚本,给这个表添加了所需的username和password列,同时在这个表中插入了一条新纪录,其Firstname、Lastname、Username、Password和roles字段分别为 “User”,“One”,“user1”,“pass1”和“user”。

USE NORTHWIND
GO
ALTER TABLE [dbo]. 
ADD [Username] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Password] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[roles] [varchar] (250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
GO
INSERT INTO EMPLOYEES (Firstname, Lastname,Username, [Password], roles)
VALUES('User','One', 'user1', 'pass1', 'user')
GO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值