代码之家  ›  专栏  ›  技术社区  ›  Stefan Steiger Marco van de Voort

保护web服务?

  •  6
  • Stefan Steiger Marco van de Voort  · 技术社区  · 15 年前

    问:我有一个文档管理系统,我正在构建一个到数据库的Web服务接口。

    如何合并密码或私钥身份验证?

    我只能找到“最佳实践”和使用“windows用户”或passport身份验证。 但我需要从数据库中存储的用户和密码进行身份验证,或者更好地为数据库中的每个web服务用户存储RSA私钥。。。

    编辑:
    我必须使用.NET框架 2.0条 在ASP.NET环境中

    5 回复  |  直到 15 年前
        1
  •  5
  •   Stefan Steiger Marco van de Voort    15 年前

    解决方案是使用MSDN和CodeProject提供的混合代码编写自己的http模块。包括自己对MS错误的修复,然后将此自定义soap头添加到web服务。

    <SoapHeader("Authentication", Required:=True)>
    

    Imports System.Web
    Imports System.Web.Services.Protocols
    
    
    ' http://msdn.microsoft.com/en-us/library/9z52by6a.aspx
    ' http://msdn.microsoft.com/en-us/library/9z52by6a(VS.80).aspx
    
    
    
    
    ' http://www.codeproject.com/KB/cpp/authforwebservices.aspx
    
    
    ' http://aleemkhan.wordpress.com/2007/09/18/using-wse-30-for-web-service-authentication/
    ' http://www.codeproject.com/KB/WCF/CustomUserNamePassAuth2.aspx
    ' http://www.codeproject.com/KB/WCF/CustomUserNamePassAuth2.aspx
    ' http://www.codeproject.com/KB/webservices/WS-Security.aspx
    
    
    
    
    'Public NotInheritable Class WebServiceAuthenticationModule
    Public Class WebServiceAuthenticationModule
        Implements System.Web.IHttpModule
    
        Protected Delegate Sub WebServiceAuthenticationEventHandler(ByVal sender As [Object], ByVal e As WebServiceAuthenticationEvent)
        Protected _eventHandler As WebServiceAuthenticationEventHandler = Nothing
    
    
    
        Protected Custom Event Authenticate As WebServiceAuthenticationEventHandler
            AddHandler(ByVal value As WebServiceAuthenticationEventHandler)
                _eventHandler = value
            End AddHandler
            RemoveHandler(ByVal value As WebServiceAuthenticationEventHandler)
                _eventHandler = value
            End RemoveHandler
            RaiseEvent(ByVal sender As Object,
                    ByVal e As WebServiceAuthenticationEvent)
            End RaiseEvent
        End Event
    
    
        Protected app As HttpApplication
    
    
        Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
            app = context
    
            context.Context.Response.Write("<h1>Test</h1>")
    
            AddHandler app.AuthenticateRequest, AddressOf Me.OnEnter
        End Sub
    
    
        Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
            ' add clean-up code here if required
        End Sub
    
    
        Protected Sub OnAuthenticate(ByVal e As WebServiceAuthenticationEvent)
            If _eventHandler Is Nothing Then
                Return
            End If
            _eventHandler(Me, e)
            If Not (e.User Is Nothing) Then
                e.Context.User = e.Principal
            End If
    
        End Sub 'OnAuthenticate 
    
    
        Public ReadOnly Property ModuleName() As String
            Get
                Return "WebServiceAuthentication"
            End Get
        End Property
    
    
        Sub OnEnter(ByVal [source] As [Object], ByVal eventArgs As EventArgs)
            'Dim app As HttpApplication = CType([source], HttpApplication)
            'app = CType([source], HttpApplication)
            Dim context As HttpContext = app.Context
            Dim HttpStream As System.IO.Stream = context.Request.InputStream
    
            ' Save the current position of stream.
            Dim posStream As Long = HttpStream.Position
    
            ' If the request contains an HTTP_SOAPACTION 
            ' header, look at this message.
    
            'For Each str As String In context.Request.ServerVariables.AllKeys
    
            'If context.Request.ServerVariables(Str) IsNot Nothing Then
            'context.Response.Write("<h1>" + Str() + "= " + context.Request.ServerVariables(Str) + "</h1>")
            'End If
            'Next
            If context.Request.ServerVariables("HTTP_SOAPACTION") Is Nothing Then
                'context.Response.End()
                Return
                'Else
                'MsgBox(New System.IO.StreamReader(context.Request.InputStream).ReadToEnd())
            End If
    
    
            ' Load the body of the HTTP message
            ' into an XML document.
            Dim dom As New System.Xml.XmlDocument()
            Dim soapUser As String
            Dim soapPassword As String
    
            Try
                dom.Load(HttpStream)
    
                'dom.Save("C:\Users\Administrator\Desktop\SoapRequest.xml")
                ' Reset the stream position.
                HttpStream.Position = posStream
    
                ' Bind to the Authentication header.
                soapUser = dom.GetElementsByTagName("Username").Item(0).InnerText
                soapPassword = dom.GetElementsByTagName("Password").Item(0).InnerText
            Catch e As Exception
                ' Reset the position of stream.
                HttpStream.Position = posStream
    
                ' Throw a SOAP exception.
                Dim name As New System.Xml.XmlQualifiedName("Load")
                Dim ssoapException As New SoapException("Unable to read SOAP request", name, e)
                context.Response.StatusCode = System.Net.HttpStatusCode.Unauthorized
                context.Response.StatusDescription = "Access denied."
    
                ' context.Response.Write(ssoapException.ToString())
                'Dim x As New System.Xml.Serialization.XmlSerializer(GetType(SoapException))
                'context.Response.ContentType = "text/xml"
                'x.Serialize(context.Response.OutputStream, ssoapException)
    
    
                'Throw ssoapException
    
                context.Response.End()
            End Try
    
            ' Raise the custom global.asax event.
            OnAuthenticate(New WebServiceAuthenticationEvent(context, soapUser, soapPassword))
            Return
        End Sub 'OnEnter
    
    
    End Class ' WebServiceAuthenticationModule
    
        2
  •  4
  •   BrokenGlass    15 年前

    如果您仍在使用ASP.NET SOAP web服务,那么符合您的IMO要求的最简单方法是使用带有成员身份数据库的ASP.NET Forms身份验证。如果你刚开始的话,我建议你使用WCF——如果你不能/或者不愿意这样做,这篇文章将适用于“经典”的ASP.NET SOAP web服务。

    1. 将其配置为与对任何其他网站一样,但将其设置为允许所有人访问:

      <authorization>
          <allow users="*"/>
      </authorization>
      
    2. 实现登录/注销方法,并在登录方法中颁发身份验证票证。然后,对web服务的进一步请求可以使用已颁发的身份验证票证。

    3. [原则权限(SecurityAction.Demand,Authenticated=true)]

    如果客户端未通过身份验证,这些方法现在将引发安全异常。

    受保护方法的示例:

    [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
    [WebMethod(Description = "Your protected method")]
    public string Foo()
    {
        return "bar";
    }
    

    [WebMethod(Description = "Login to start a session")]
    public bool Login(string userName, string password)
    {
        if (!Membership.Provider.ValidateUser(userName, password))
            return false;
    
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
               1,
               userName,
               DateTime.Now,
               DateTime.Now.AddMinutes(500),
               false,
               FormsAuthentication.FormsCookiePath);// Path cookie valid for
    
        // Encrypt the cookie using the machine key for secure transport
        string hash = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, // Name of auth cookie
                                           hash); // Hashed ticket
    
        // Set the cookie's expiration time to the tickets expiration time
        if (ticket.IsPersistent)
            cookie.Expires = ticket.Expiration;
    
        // Add the cookie to the list for outgoing response
        if(HttpContext.Current !=null)
            HttpContext.Current.Response.Cookies.Add(cookie);
    
        FormsAuthentication.SetAuthCookie(userName, true);
        return true;
    }
    
        3
  •  2
  •   Jacob    15 年前

    如果您使用的是WCF,那么有一种使用X509证书实现安全性的简单方法。使用安全模式“Message”和clientCredentialType“Username”实现绑定可以自动保证此安全性。

    可以通过类wich覆盖方法Validate进行验证。

    http://msdn.microsoft.com/en-us/library/aa702565.aspx

        4
  •  0
  •   ArBR    15 年前

    如果要通过SOAP协议使用WS,则可以通过SOAP头实现安全性:

    using System.Web.Services;
    using System.Web.Services.Protocols;
    
    namespace Domain.WS
    {
        [Serializable]
        public class SoapWSHeader : System.Web.Services.Protocols.SoapHeader, ISoapWSHeader
        {
            public string UserId { get; set; }
            public string ServiceKey { get; set; }
            public ApplicationCode ApplicationCode { get; set; }        
        }    
    
        [WebService(Namespace = "http://domain.some.unique/")]        
        public class MyServices : System.Web.Services.WebService
        {
            public SoapWSHeader WSHeader;
            private ServicesLogicContext _logicServices;
    
            public MyServices() { _logicServices = new ServicesLogicContext(new LogicInfo() {...}); }
    
            [WebMethod, SoapHeader("WSHeader", Direction = SoapHeaderDirection.InOut)]
            public Result WSMethod1(Int32 idSuperior)
            {
                _logicServices.ThrowIfNotAuthenticate(WSHeader); 
                return _logicServices.WSMethod1(idSuperior) as Result;
            }
        }
    }
    
    namespace Domain.Logic 
    {
        [Serializable]    
        public class ServicesLogicContext : ServicesLogicContextBase
        {
            protected ISoapWSHeader SoapWSHeader { get; set; }
            public ServicesLogicContext(LogicInfo info) : base(info) {}
    
            public IResult WSMethod1(Int32 idSuperior)
            {
                IResult result = null; 
                //-- method implementation here...
                return result;
            }
    
            public void ThrowIfNotAuthenticate(ISoapWSHeader soapWSHeader) {
                this.SoapWSHeader = soapWSHeader;
                if (SoapWSHeader != null)
                {
                    if (!ValidateCredentials(soapWSHeader))
                    {
                        throw new System.Security.SecurityException(Resources.ValidationErrorWrongCredentials);
                    }
                }
                else { throw new System.Security.SecurityException(Resources.ValidationErrorWrongWSHeader); }
            }
            private bool ValidateCredentials(ISoapWSHeader soapWSHeader) {   
                return (SoapWSHeader.UserId.Equals("USER_ID") && SoapWSHeader.ServiceKey.Equals("PSW_1"));
            }
        }
    }
    

        5
  •  0
  •   Robert Paulson    9 年前

    在进行自己的身份验证之前,您可能需要查看 Web Services Enhancements (WSE) 2.0 SP3 for Microsoft .NET WS-Security .net规范。

    wse 2.0 WS-Security