2010-10-20 39 views
7

Câu hỏi: Tôi có một hệ thống quản lý tài liệu và tôi đang xây dựng một giao diện Web-Dịch vụ cho cơ sở dữ liệu.Đảm bảo dịch vụ web?

Mọi thứ hoạt động cho đến thời điểm này, ngay bây giờ, nó hoàn toàn không được bảo đảm, mọi người đều có thể truy cập.

Tôi làm cách nào để kết hợp mật khẩu hoặc xác thực khóa công khai riêng?

Tôi chỉ có thể tìm thấy 'các phương pháp hay nhất' và sử dụng 'người dùng cửa sổ' hoặc xác thực hộ chiếu. Nhưng tôi cần phải xác thực từ người dùng và mật khẩu được lưu trữ trong cơ sở dữ liệu, hoặc tốt hơn cho một RSA tin-key được lưu trữ cho mỗi người dùng web-dịch vụ trong cơ sở dữ liệu ...

Edit:
tôi phải sử dụng Khuôn khổ .NET 2.0 trong môi trường ASP.NET

Trả lời

6

Giải pháp là để viết một module http riêng với một hỗn hợp của mã được cung cấp bởi MSDN và CodeProject. Bao gồm sửa lỗi riêng của MS lỗi, và sau đó thêm tiêu đề xà phòng tùy chỉnh này vào dịch vụ web.

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

Đây là mô-đun:

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

Nếu bạn đang làm việc với WCF, có một cách dễ dàng để thực hiện bảo mật bằng chứng chỉ X509. Thực hiện một ràng buộc với chế độ bảo mật 'Message' và clientCredentialType 'Username' nó có thể đảm bảo an ninh này một cách tự động.

Việc xác thực có thể được thực hiện thông qua lớp đã ghi đè phương thức Xác thực.

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

+1

+1, nhưng thật không may, tôi bị giới hạn ở ASP.NET với khung 2.0, do đó không có WCF. –

+0

Ops, tôi bị mất trong trường hợp đó, tôi hiểu rằng thông tin liên lạc ở cấp độ vận tải có thể được thực hiện với chứng chỉ X509. Có lẽ quá trình xác nhận đối với SQL Server sẽ có nhiều 'thủ công' hơn. Dù sao bạn có thể tìm thêm thông tin tại: http://msdn.microsoft.com/en-us/library/ms996415.aspx – IoChaos

1

Trước khi bạn cuộn xác thực của riêng bạn, bạn có thể muốn có một cái nhìn tại Web Services Enhancements (WSE) 2.0 SP3 for Microsoft .NET. Đó là việc triển khai đặc tả WS-Security cho .net.

google wse 2.0 hoặc WS-Security để biết thêm liên kết.

+0

liên kết đến WSE bị hỏng - tác giả có thể sửa lại không? –

5

Nếu bạn vẫn đang sử dụng dịch vụ web ASP.NET SOAP thì cách dễ nhất phù hợp với yêu cầu của bạn IMO là sử dụng xác thực Mẫu ASP.NET với một DB thành viên. Nếu bạn đang bắt đầu ra tươi tôi muốn khuyên bạn nên đi với WCF - nếu bạn không thể/hoặc sẽ không làm điều đó đăng bài áp dụng cho các "cổ điển" ASP.NET SOAP dịch vụ web.

Để thêm hình thức xác thực cho một dịch vụ web:

  1. Cấu hình nó giống như bạn làm cho bất kỳ trang web khác, nhưng thiết lập nó cho phép truy cập cho tất cả mọi người:

    <authorization> 
        <allow users="*"/> 
    </authorization> 
    
  2. Thực hiện các phương thức Đăng nhập/Đăng xuất và phát hành vé xác thực trong phương thức Đăng nhập. Các yêu cầu khác đối với dịch vụ web sau đó có thể sử dụng vé xác thực đã phát hành.

  3. Tất cả các phương pháp web khác mà bạn muốn bảo vệ sau đó bạn có thể trang trí với

    [PrincipalPermission (SecurityAction.Demand, Authenticated = true)]

Những phương pháp này bây giờ sẽ ném một ngoại lệ an ninh nếu một khách hàng không được xác thực.

Ví dụ cho một phương pháp bảo vệ:

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

Ví dụ cho phương pháp nhập:

[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; 
} 
+0

Và sau đó bạn sẽ phải gọi đăng nhập và đăng xuất mỗi khi bạn muốn sử dụng dịch vụ web, với hệ thống truyền hộp đen và hành vi không xác định nếu máy khách hoặc máy chủ bị treo ở giữa. Và nếu bạn quên thêm PrincipalPermission vào một phương thức duy nhất ... Nono, bất cứ thứ gì muốn nghiêm túc phải từ chối truy cập theo mặc định, và chỉ lấy dữ liệu đăng nhập như một tham số dịch vụ chứ không phải là phương thức. –

+0

Nó không khác gì so với xác thực biểu mẫu UI thông thường, vẫn dễ dàng hơn để có được các nhược điểm được đề cập hơn là tự cuộn của bạn. Ngoài ra, bạn còn có các tính năng Vai trò/Tư cách thành viên miễn phí. Mặc dù điểm mặc định được bảo mật. – BrokenGlass

0

Nếu WS của bạn sẽ được tiêu thụ thông qua giao thức SOAP, các bạn có thể thực hiện Bảo mật thông qua tiêu đề 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")); 
     } 
    } 
} 

Lưu ý: mã này chưa hoàn chỉnh, điều này chỉ mô tả các khía cạnh chính về cách sử dụng Tiêu đề SOAP.

+0

Nếu bạn đã chú ý, thì bạn đã nhận ra rằng đây chính xác là những gì tôi đã làm. Chỉ cần tôi đã di chuyển xác thực từ kết hợp vào mọi WebMethod, đó là bs, để mô-đun HTTP nói. Với tiền thưởng thêm vào, nó từ chối truy cập vào mọi cuộc gọi SOAP mà không có tiêu đề. –

+0

Ok, điều đó có nghĩa là bạn đã giải quyết được vấn đề của mình. Trân trọng, chúng tôi đang áp dụng kỹ thuật đó để bảo mật một số WS, ngoài ra, tùy thuộc vào ứng dụng của bạn, bạn có thể sử dụng một số chứng chỉ thông qua HTTPS. – ArBR

Các vấn đề liên quan