C# 保护web服务?
问题:我有一个文档管理系统,我正在构建一个数据库的Web服务接口 到目前为止一切正常,只是现在,它完全不安全,每个人都可以访问它 如何合并密码或私有公钥身份验证 我只能找到“最佳实践”和使用“windows用户”或passport身份验证。 但是我需要用户的身份验证和数据库中存储的密码,或者更好的是为数据库中的每个web服务用户存储RSA私钥 编辑:C# 保护web服务?,c#,vb.net,web-services,security,C#,Vb.net,Web Services,Security,问题:我有一个文档管理系统,我正在构建一个数据库的Web服务接口 到目前为止一切正常,只是现在,它完全不安全,每个人都可以访问它 如何合并密码或私有公钥身份验证 我只能找到“最佳实践”和使用“windows用户”或passport身份验证。 但是我需要用户的身份验证和数据库中存储的密码,或者更好的是为数据库中的每个web服务用户存储RSA私钥 编辑: 我必须在ASP.NET环境中使用.NET Framework2.0如果您使用的是WCF,有一种使用X509证书实现安全性的简单方法。通过使用安全模
我必须在ASP.NET环境中使用.NET Framework2.0如果您使用的是WCF,有一种使用X509证书实现安全性的简单方法。通过使用安全模式“Message”和clientCredentialType“Username”实现绑定,可以自动保证这种安全性 验证可以通过覆盖验证方法的类进行
解决方案是使用MSDN和CodeProject提供的混合代码编写自己的http模块。包括自己的MS Bug修复,然后将此自定义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
导入系统.Web
导入System.Web.Services.Protocols
' http://msdn.microsoft.com/en-us/library/9z52by6a.aspx
' http://msdn.microsoft.com/en-us/library/9z52by6a(第80节)
' 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
'公共不可继承类WebServiceAuthenticationModule
公共类WebServiceAuthenticationModule
实现System.Web.IHttpModule
受保护的委托子WebServiceAuthenticationEventHandler(ByVal发件人作为[Object],ByVal e作为WebServiceAuthenticationEvent)
受保护的_eventHandler作为WebServiceAuthenticationEventHandler=无
受保护的自定义事件身份验证为WebServiceAuthenticationEventHandler
AddHandler(作为WebServiceAuthenticationEventHandler的ByVal值)
_eventHandler=value
EndAddHandler
RemoveHandler(作为WebServiceAuthenticationEventHandler的ByVal值)
_eventHandler=value
末端移除处理器
RaiseEvent(ByVal发送方作为对象,
ByVal e As WebServiceAuthenticationEvent)
端部提升孔
结束事件
作为HttpApplication的受保护应用程序
Public Sub Init(ByVal上下文作为System.Web.HttpApplication)实现System.Web.IHttpModule.Init
app=上下文
context.context.Response.Write(“测试”)
AddHandler app.AuthenticateRequest,AddressOf Me.oneter
端接头
Public Sub Dispose()实现System.Web.IHttpModule.Dispose
'如果需要,在此处添加清理代码
端接头
受保护的子OnAuthentication(ByVal e作为WebServiceAuthenticationEvent)
如果_eventHandler为空,则
返回
如果结束
_事件处理程序(Me,e)
如果不是(e.User为空),则
e、 Context.User=e.Principal
如果结束
结束Sub’OnAuthenticate
作为字符串的公共只读属性ModuleName()
得到
返回“WebServiceAuthentication”
结束
端属性
子OnEnter(ByVal[source]作为[Object],ByVal eventArgs作为eventArgs)
'作为HttpApplication的Dim应用程序=CType([来源],HttpApplication)
'app=CType([source],HttpApplication)
Dim context作为HttpContext=app.context
将HttpStream设置为System.IO.Stream=context.Request.InputStream
'保存流的当前位置。
Dim posStream As Long=HttpStream.Position
'如果请求包含HTTP\U SOAPACTION
'标题,请查看此消息。
'对于context.Request.ServerVariables.AllKeys中的每个str作为字符串
'如果context.Request.ServerVariables(Str)不是空,那么
'context.Response.Write(“+Str()+”=“+context.Request.ServerVariables(Str)+”“)
"完"
”“接着呢
如果context.Request.ServerVariables(“HTTP_SOAPACTION”)什么都不是,那么
'context.Response.End()
返回
”“否则呢
'MsgBox(新System.IO.StreamReader(context.Request.InputStream.ReadToEnd())
如果结束
'加载HTTP消息的正文
'转换为XML文档。
Dim dom作为新的System.Xml.XmlDocument()
将用户设置为字符串
将soapPassword设置为字符串
尝试
Load(HttpStream)
'dom.Save(“C:\Users\Administrator\Desktop\SoapRequest.xml”)
'重置流位置。
HttpStream.Position=posStream
'绑定到身份验证标头。
soapUser=dom.GetElementsByTagName(“用户名”).Item(0).InnerText
soapPassword=dom.GetElementsByTagName(“密码”).Item(0).InnerText
捕获e作为例外
'重置流的位置。
HttpStream.Position=posStream
'抛出一个SOAP异常。
Dim名称为New System.Xml.XmlQualifiedName(“加载”)
Dim ssoapException作为新的SoapException(“无法读取SOAP请求”,名称,e)
context.Response.StatusCode=System.Net.HttpStatusCode.Unauthorized
context.Response.StatusDescription=“访问被拒绝。”
'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)
'抛出异常
context.Response.End()
结束尝试
'引发自定义global.asax事件。
奥纳图森蒂
<authorization>
<allow users="*"/>
</authorization>
[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;
}
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"));
}
}
}