webservice接口验证

webservice接口使用方便,兼容性强,目前web服务很多采用这种方式

开发webservice接口也很简单,本文主要涉及webservice中xml的验证。

1.XSD数据验证

目前交流行的是xsd数据格式验证

一个简单的xsd文档

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XSDEmrNotes"
   
    elementFormDefault="qualified"
   
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
     
>
 <xs:element name="EmrNotes">
    <xs:complexType>
      <xs:sequence>
          <xs:element name="id" type="idT"/>
        <xs:element name="User" type="UserT"/>
        <xs:element name="pwd" type="pwdT"/>
        <xs:element name="Name" type="NameT"/>
     </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="idT">
    <xs:restriction base="xs:int">
      <xs:pattern value="[0-9]{1,12}"/>
    </xs:restriction>
  </xs:simpleType>
  
  <xs:simpleType name="UserT">
    <xs:restriction base="xs:string">
      <xs:maxLength value="100"/>
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>


  <xs:simpleType name="pwdT">
    <xs:restriction base="xs:int">
      <!--[0-9]{18}|[0-9]{17}X|[0-9]{17}x|[0-9]{17}|[0-9]{15}-->
      <xs:pattern value="[0-9]{1,18}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="NameT">
    <xs:restriction base="xs:string">
      <xs:maxLength value="100"/>
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>
pattern为限制条件,采用正则

对应的xml文档为

<?xml version="1.0" encoding="utf-8" ?>
<EmrNotes >
  <id>123</id>                     
  <User>用户名</User>                 
  <pwd>1234567891</pwd>
<Name>姓名</Name>
</EmrNotes>

这里需要注意的是如果要命名空间的话,xml与xsd的命名空间需要一致,但是命名空间容易在以后的序列化中出现问题,所以全不要命名空间

二者之间需要匹配验证,为此写了一个验证类,这时构造函数:

        /// <summary>
        /// 构造验证类
        /// </summary>
        /// <param name="xmlString">xml实体</param>
        /// <param name="Sheet">表名</param>
        public  ValidationWebModel(string xmlString, string Sheet)
        {
            dataSheet = Sheet;
            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.Add(null, System.Web.HttpContext.Current.Server.MapPath("~/XXX/xml/XXX/" + dataSheet + "/" + dataSheet + ".xsd"));

           
            settings.ValidationEventHandler += new ValidationEventHandler(this.ValidationEventHandler);
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = schemaSet;

            xmlByte = Encoding.UTF8.GetBytes(xmlString);

            dataSheet = Sheet;

        }

验证的话使用xmlReader流过一遍,就像这样 while (xmlRead.Read()){}.早期也有人使用XmlSchemaCollection与XmlValidatingReader的方式来验证,也可以,但是目前MSDN上此方法已过时,所以不采用。

当然我们还需要一个ValidationEventHandler方法供XmlSchemaSet 作为过滤方法,所以定义如下

   /// <summary>
        /// 验证传入的xml文档是否符合规范
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ValidationEventHandler(Object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Warning)
            {
                // errorMassage = "插入成功." + e.Message;
                dataMessage = e.Message;
            }
            else if (e.Severity == XmlSeverityType.Error)
            {
                errorMassage = "插入失败," + e.Message;
            }

        }

整个类

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using TeleStrokes;
using UsersInfo;

namespace TeleStrokesWeb.webService
{
    public class ValidationWebModel
    {
        //业务操作类
        EmrNotesBLL emrNotesBll=new EmrNotesBLL();
        UsersBLL usersBll = new UsersBLL();
        //EmrAcceBLL emrAcceBll;
        //xml设置规则
        XmlReaderSettings settings = new XmlReaderSettings();
        //数据表名
        string dataSheet;

        //传入的字节
        byte[] xmlByte;
        /// <summary>
        /// 要返回的错误信息
        /// </summary>
        public  string errorMassage
        { get; set; }

        /// <summary>
        /// 数据详情
        /// </summary>
        public string dataMessage
        { get; set; }

        /// <summary>
        /// 构造验证类
        /// </summary>
        /// <param name="xmlString">xml实体</param>
        /// <param name="Sheet">表名</param>
        public  ValidationWebModel(string xmlString, string Sheet)
        {
            dataSheet = Sheet;
            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.Add(null, System.Web.HttpContext.Current.Server.MapPath("~/Dictionary/xml/TeleStrokes/" + dataSheet + "/" + dataSheet + ".xsd"));

           
            settings.ValidationEventHandler += new ValidationEventHandler(this.ValidationEventHandler);
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = schemaSet;

            xmlByte = Encoding.UTF8.GetBytes(xmlString);

            dataSheet = Sheet;

        }

      /// <summary>
        ///  开始验证方法
      /// </summary>
      /// <param name="dataSheet">要使用的数据表</param>
      /// <returns></returns>
        public  T Check<T>()where T:class
        {
            using (MemoryStream ms = new MemoryStream(xmlByte))
            {
                using (XmlReader xmlRead = XmlReader.Create(ms, settings))
                {
                    while (xmlRead.Read())
                    {

                    }
                    if (string.IsNullOrEmpty(errorMassage))
                    {
                        ms.Position = 0;

                        //验证成功,符合规范
                        ms.Position = 0;
                        if (dataSheet == "EmrAcce")
                        {
                            //验证附件表
                            T result = SeralizeModel<T>(ms,CheckEmrNotesRealtion );
                            return result;
                        }
                        else if (dataSheet == "EmrNotes") 
                        {
                            //验证病历表
                            Func<object, bool> notesValidate = CheckUserRelation;
                            notesValidate += ValidateIp;
                            notesValidate += CheckAddUser;

                            T result = SeralizeModel<T>(ms, notesValidate);
                            return result;
                        }
                        else
                        {
                            errorMassage = "传错表了";
                            return null;
                        }
                     //  return  SeralizeModel(ms, dataSheet);
                       
                    }
                    else
                    {
                        return default(T);
                    }
                }
            }
        }

        /// <summary>
        /// 序列化并且验证表实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader"></param>
        /// <param name="validate"></param>
        /// <returns></returns>
        private T SeralizeModel<T>(Stream reader,Func<object,bool> validate)where T:class
        {
            T newModel = XmlSerializer<T>(reader);

            validate(newModel);

            return newModel;

        }

        /// <summary>
        /// 序列化传入的流对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="stream"></param>
        /// <returns></returns>
        private T XmlSerializer<T>(Stream stream)where T:class
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            T tModel = ser.Deserialize(stream) as T ;
            return tModel;
        }
 

        /// <summary>
        /// 如果存在病人用户名验证是否在用户表中,返回警告信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="newEmrNote"></param>
        /// <returns></returns>
        private bool CheckUserRelation(object newEmrNote)
        {
            EmrNotes newEmrNotes = (EmrNotes)newEmrNote;
           
            if (!string.IsNullOrEmpty(newEmrNotes.EnUser))
            {
                if (usersBll.GetUsersCheck(newEmrNotes.EnUser)) { return true;}
                else
                {
                    dataMessage = "病人用户不是系统注册用户";
                    return false;
                }

            }
            return false;
        }

        /// <summary>
        /// 检查录入员是否是系统用户
        /// </summary>
        /// <param name="newEmrNote"></param>
        /// <returns></returns>
        private bool CheckAddUser(object newEmrNote)
        {
            EmrNotes newEmrNotes = (EmrNotes)newEmrNote;
            if (!string.IsNullOrEmpty(newEmrNotes.EnAddUser))
            {
                if (usersBll.GetUsersCheck(newEmrNotes.EnAddUser)) { return true; }
                else
                {
                    dataMessage = "录入员不是系统注册用户";
                    return false;
                }

            }
            return false;
        }


       /// <summary>
        /// 检查传入的附件有无病历表中的相关项
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="newEmrAcce"></param>
       /// <returns></returns>
        private bool CheckEmrNotesRealtion(object newEmrAcce)
        {
            EmrAcce newModel = (EmrAcce)newEmrAcce;
            //验证是否是之前的数据关联
            EmrNotes result = emrNotesBll.GetEmrNotes(newModel.Enid);
            if (result == null)
            {
                errorMassage = "没有相关病历的记录,请先传入病历表";
                return false;
            }
            else
            {

                return true;
            }
        }


        /// <summary>
        /// 验证传入的xml文档是否符合规范
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ValidationEventHandler(Object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Warning)
            {
                // errorMassage = "插入成功." + e.Message;
                dataMessage = e.Message;
            }
            else if (e.Severity == XmlSeverityType.Error)
            {
                errorMassage = "插入失败," + e.Message;
            }

        }

        /// <summary>
        /// 根据ip验证是否是用户本人
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        private bool ValidateIp(object AcceNotes)
        {
            string userName=((EmrNotes)AcceNotes).EnAddUser;
            if (string.IsNullOrEmpty(userName)) return true;
            Users currentUser = usersBll.GetUsers(userName);
            if (currentUser!=null)
            {
                if (!string.IsNullOrEmpty(currentUser.URegIp))
                {
                    if (currentUser.URegIp != GetIp())
                    {
                        //此处列为警告信息
                      //  errorMassage = "录入员用户的ip地址不对";
                        dataMessage = "录入员用户的ip地址不对";
                        return false;
                    }
                }
               
            }

            return true;
        }

        /// <summary>
        /// 获得iP地址
        /// </summary>
        /// <returns></returns>
        private string GetIp()
        {
          
            string ip = "";

            if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)// 服务器变量, using proxy
            {
                ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
            }
            if (ip == "" || ip == null)//如果没有使用代理服务器或者得不到客户端的ip  
            {                            //得到服务端的地址    

                ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString(); //While it can't get the Client IP, it will return proxy IP.


                if (ip == "" || ip == null)//如果没有使用代理服务器或者得不到客户端的ip  not using proxy or cant get the Client IP
                {
                    string strHostName = System.Net.Dns.GetHostName();

                    string clientIPAddress = System.Net.Dns.GetHostAddresses(strHostName).GetValue(0).ToString();
                }

                if (ip == "" || ip == null)
                {
                    ip = HttpContext.Current.Request.UserHostAddress;
                }

            }
            return ip;
        }    
    }
}
View Code

2.soapHeader验证

首先声明一个soapHeader的子类

    public class SoapHeaderValidate:System.Web.Services.Protocols.SoapHeader
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName
        { get; set; }
        /// <summary>
        /// 密码
        /// </summary>
        public string UserPwd
        { get; set; }
        /// <summary>
        /// 构造函数1
        /// </summary>
        public SoapHeaderValidate()
         {
            
         }
        /// <summary>
        /// 构造函数2
        /// </summary>
        /// <param name="UserName"></param>
        /// <param name="UserPwd"></param>
        public SoapHeaderValidate(string userName, string userPwd)
        {
            UserName = userName;
            UserPwd = userPwd;
        }
}

然后在类中写一些验证方法

  /// <summary>
        /// 主调方法:用于验证是否调用接口的用户存在
        /// </summary>
        /// <param name="ErroMsg"></param>
        /// <returns></returns>
        public  bool IsValid(out string ErroMsg)
        {
            ErroMsg = "";
            try
            {
                if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(UserPwd)) 
                {
                    ErroMsg = "没有传递用户名";
                    return false;
                }

                UsersBLL userBll = new UsersBLL();
                //暂定为测试有无用户名,以后改为状态或者登陆验证
                if (!userBll.GetUsersCheck(UserName)) 
                {
                    ErroMsg = "用户名错误";
                    return false;
                }
                return true;
            }
            catch (Exception)
            {
                
                throw;
            }
        }

然后回到接口处在接口大类中声明了这个soapHeader后,添加如下标签

  [SoapHeader("myHeader")]
        [WebMethod(Description = "测试soap连接方法,返回ok")]
        public string Hello()
        {
            string msg = string.Empty;
            if (myHeader.IsValid(out msg)) return msg;
            return "Ok";
        }

接口写上

     string msg = string.Empty;
            if (!myHeader.IsValid(out msg))
            {
                return msg;
            }

ok,别人发送的信息就必须得通过头部验证了

客户端使用方式

  SendData.SoapHeaderValidate myHeader = new SendData.SoapHeaderValidate();
            myHeader.UserName = "bingren1";//
            myHeader.UserPwd = "111";

把这个声明的头加到web方法的首个参数就可以了

原文地址:https://www.cnblogs.com/wanglao/p/3673831.html