WebService 的创建及安全调用
2011-08-05 19:58 哒不溜 阅读(397) 评论(1) 编辑 收藏 举报Web Service的基本概念估计大家都比较的熟悉,我就不多说了。咱直接从头动手吧:
1,首先创建一个Web网站,我这里取名叫WebServiceStudy, 在WebServiceStudy站点中添加新项 选择"Web 服务",我这里取名为WebServiceStudy.asmx。
2,创建好web服务后,我们就可以在App_Code/WebServiceStudy.cs下开始我们要写的接口方法了。
由于前两步骤比较简单,大部分同学都懂,我也就没详细陈述,开始第三步骤吧?
3,App_Code/WebServiceStudy.cs下 删除没用的HelloWorld()方法。我添加一个测试方法如下:
[WebMethod]
public DataTable WervicesTest()
{
DataTable dt = new DataTable("Test");
dt.Columns.Add(new DataColumn("col1", typeof(System.String)));
dt.Columns.Add(new DataColumn("col2", typeof(System.String)));
for (int i = 0; i < 5; i++)
{
DataRow dr = dt.NewRow();
dr[0] = i.ToString();
dr[1] = i.ToString();
dt.Rows.Add(dr);
}
return dt;
}
在我的WervicesTest() 方法中返回的是一个DataTable 类型,这样是有目的的,因为在和同事的交流过程中,我返现很多同事认为WebService 只能反回String类型。
这样好像就完了?很多同学说:接下来部署网站,添加webservice 引用,调用方法。所有介绍WebService的博客都是这样子滴。
4,对于上面的方法,每个人都可以调用,所以我们得带点安全性吧? 那我们就添加一个身份验证。继续……
WebServiceStudy站点下,新建类WebServiceSoaps.cs 代码如下:
public class WebServiceSoaps : System.Web.Services.Protocols.SoapHeader
{
/// <summary>
/// 验证用户名
/// </summary>
public string CheckUserName
{
get;
set;
}
/// <summary>
/// 验证用户密码
/// </summary>
public string CheckPwd
{
get;
set;
}
}
一定要注意 继承:System.Web.Services.Protocols.SoapHeader
下面这段话是我从MSDN摘抄下来的对 SoapHeader 类的备注,我的理解仅仅局限于望文生义,所以还是用MSDN的原话来的方便,更多内容可查看SoapHeader 类。
SOAP 标头提供了一种方法,用于将数据传递到 XML Web services 方法或从 XML Web services 方法传递数据,条件是该数据不直接与 XML Web services 方法的主功能相关。例如,一个 XML Web services 可能包含若干个 XML Web services 方法,而每个方法都需要自定义的身份验证方案。您不用将参数添加到每个需要自定义身份验证方案的 XML Web services 方法,而可以将引用从 SoapHeader 派生的类的 SoapHeaderAttribute 应用于每个 XML Web services 方法。从 SoapHeader 派生的类的实现处理该自定义身份验证方案。按照此方式,XML Web services 方法使用 SOAP 标头来仅实现特定于它的功能并添加其他功能。
5,在创建个加密解密类Encrypt.cs吧?呵呵
代码如下:
public class Encrypt { //密钥 private static string sKey = "A3F2569E6SJEAWBCJOTY45DYQWF88H1Y"; //矢量,矢量可以为空 private static string sIV = "qdCy6X+aKLw="; /// <summary> /// MD5加密 /// </summary> /// <param name="str">要加密的串</param> /// <param name="code">16 16位加密,32 32位加密</param> /// <returns></returns> public static string MD5(string str, int code) { str = str.ToLower(); if (code == 16) //16位MD5加密(取32位加密的9~25字符) { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower().Substring(8, 16); } if (code == 32) //32位加密 { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower(); } return "00000000000000000000000000000000"; } /// <summary> /// 加密 /// </summary> /// <param name="Value"></param> /// <returns></returns> public static string EncryptString(string value) { if (!String.IsNullOrEmpty(value)) { SymmetricAlgorithm mCSP = new TripleDESCryptoServiceProvider(); ICryptoTransform ct; MemoryStream ms; CryptoStream cs; byte[] byt; mCSP.Key = Convert.FromBase64String(sKey); mCSP.IV = Convert.FromBase64String(sIV); //指定加密的运算模式 mCSP.Mode = System.Security.Cryptography.CipherMode.ECB; //获取或设置加密算法的填充模式 mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7; ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV); byt = Encoding.UTF8.GetBytes(value); ms = new MemoryStream(); cs = new CryptoStream(ms, ct, CryptoStreamMode.Write); cs.Write(byt, 0, byt.Length); cs.FlushFinalBlock(); cs.Close(); return Convert.ToBase64String(ms.ToArray()); } else { return ""; } } /// <summary> /// 解密 /// </summary> /// <param name="Source"></param> /// <returns></returns> public static string DecrypString(string source) { if (!String.IsNullOrEmpty(source)) { try { SymmetricAlgorithm mCSP = new TripleDESCryptoServiceProvider(); byte[] bytIn = Convert.FromBase64String(source); MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length); mCSP.Mode = System.Security.Cryptography.CipherMode.ECB; //获取或设置加密算法的填充模式 mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7; mCSP.Key = Convert.FromBase64String(sKey); mCSP.IV = Convert.FromBase64String(sIV); ICryptoTransform encrypto = mCSP.CreateDecryptor(mCSP.Key, mCSP.IV); CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read); StreamReader sr = new StreamReader(cs); return sr.ReadToEnd(); } catch { return ""; } } else { return ""; } } }
6,在web.config 中添加如下配置文件
<appSettings>
<add key="WebServiceTest" value="zhangzhi,19861216"/>
</appSettings>
上面文件用来配置身份验证用的,后面将详细介绍。
7,回到App_Code/WebServiceStudy.cs 下:
添加如下代码
public WebServiceSoaps myServiceSoap = new WebServiceSoaps();//调用WebServiceSoaps类进行身份验证
//验证名
string StrName = System.Configuration.ConfigurationManager.AppSettings["WebServiceTest"].Split(',')[0].ToString();
//验证密码
string StrPwd = System.Configuration.ConfigurationManager.AppSettings["WebServiceTest"].Split(',')[1].ToString();
然后修改WervicesTest()方法。
整个App_Code/WebServiceStudy.cs 下的WebServiceStudy类如下:
public class WebServiceStudy : System.Web.Services.WebService { public WebServiceSoaps myServiceSoap = new WebServiceSoaps();//调用WebServiceSoaps类进行身份验证 //验证名 string StrName = System.Configuration.ConfigurationManager.AppSettings["WebServiceTest"].Split(',')[0].ToString(); //验证密码 string StrPwd = System.Configuration.ConfigurationManager.AppSettings["WebServiceTest"].Split(',')[1].ToString(); public WebServiceStudy () { //如果使用设计的组件,请取消注释以下行 //InitializeComponent(); } [System.Web.Services.Protocols.SoapHeader("myServiceSoap")] [WebMethod] public DataTable WervicesTest() { DataTable dt = new DataTable("Test"); dt.Columns.Add(new DataColumn("col1", typeof(System.String))); dt.Columns.Add(new DataColumn("col2", typeof(System.String))); if (myServiceSoap.CheckUserName.Equals(StrName) && Encrypt.DecrypString(myServiceSoap.CheckPwd).Equals(StrPwd)) { for (int i = 0; i < 5; i++) { DataRow dr = dt.NewRow(); dr[0] = i.ToString(); dr[1] = i.ToString(); dt.Rows.Add(dr); } } else { //logWebServices.Info("未知用户" + System.Web.HttpContext.Current.Request.UserHostAddress); DataRow dr = dt.NewRow(); dr[0] = "伙计,你没有权限!"; dr[1] = " It's only a test!"; dt.Rows.Add(dr); } return dt; } }
好了,基本的通过SOAP 标头身份验证就实现了。
接下来我们演示如何在另外的站点调用上面的Webservice 方法--WervicesTest()
7,运行WebServiceStudy.asmx服务 ,我们会看到
如下头所示:
我们暂时还是不要点击调用它了,会报错的--因为我们添加了验证。
我本机是:http://localhost:1676/WebServiceStudy/WebServiceStudy.asmx
9,再新建一个站点test
添加web引用 如下图:
我这里 "web引用名" 为WebServicetest
10, 在test站点下添加一个 default.aspx页面,拖放一个GridView 控件,id为GridView 1,GridView 控件是用来承载 接口方法返回的DataTable数据的(这里仅仅为了演示)
default.aspx.cs 页面代码如下:
protected void Page_Load(object sender, EventArgs e)
{
//web服务
WebServicetest.WebServiceStudy w = new WebServicetest.WebServiceStudy();
//web服务Soaps
WebServicetest.WebServiceSoaps soap = new WebServicetest.WebServiceSoaps();
//用户名
soap.CheckUserName = "zhangzhi";
//用户密码
//此字符传是通过Encrypt.EncryptString("19861216")加密得来的
soap.CheckPwd = "C30pzxjFiML8lFvLh4A5SA==";
w.WebServiceSoapsValue = soap;
DataTable dt = w.WervicesTest();
GridView1.DataSource = dt;
GridView1.DataBind();
}
注释:
我们一般在自己的web.config配置用户名和密码,如上面步骤6提到的WebServiceStudy站点下的
<appSettings>
<add key="WebServiceTest" value="zhangzhi,19861216"/>
</appSettings>
而把用户名和加密后的密码给调用者,如test站点的用户:(CheckUserName = "zhangzhi";soap.CheckPwd = "C30pzxjFiML8lFvLh4A5SA==";)
用户调用wenservices的方法时,传递用户名和加密后的密码,我们通过解密进行验证。
完了 ,点击default2.aspx页面 ,在浏览器中查看 ,就可以看到想要的数据了。
如图:
当然 如果你传了个错误的 密码比如"C30pzxjFiML8lFvLh4A5SA==AAAAAAAA";
提示你没有权限,如下图:
完了 ,楼下的同学有要补充的嘛?
我个人QQ:1791786556
讨论QQ群:
WPF学习交流:699150554
WPF/UI 界面开发:527847154
WPF控件编程:699191787