• 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方法的首个参数就可以了

  • 相关阅读:
    利用libxml2解析xml文档
    找出两个链表的第一个公共结点
    [转载]风雨20年:我所积累的20条编程经验
    inotify监测文件及文件夹
    [转载]linux下svn常用指令
    利用zlib进行数据压缩
    2013腾讯编程马拉松初赛:郑厂长系列故事——体检
    Socket编程之简单介绍
    C语言中static的作用总结
    写程序实现wireshark的抓包功能
  • 原文地址:https://www.cnblogs.com/wanglao/p/3673831.html
Copyright © 2020-2023  润新知