首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现WebServiceHost身份验证?

如何实现WebServiceHost身份验证?
EN

Stack Overflow用户
提问于 2013-04-10 09:43:36
回答 3查看 2.1K关注 0票数 1

我知道webservicehost类上的身份验证并不完全遵循身份验证标准(当用户输入不正确的凭据时,返回403,而不是提示输入另一组凭据)。

我仍然希望实现这种基本身份验证(会话开始时的用户名和密码,不需要HTTPS -见下图),因为它适合我对小型家庭项目的需求。

我为myService编写的代码如下:

代码语言:javascript
复制
Imports System.IO
Imports System.Text
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.ServiceModel.Channels

<ServiceContract()>
Public Class myService
    <OperationContract(), WebGet(UriTemplate:="/xml/{argument1}/{argument2}")>
    Public Function XML(argument1 As String, argument2 As String) As Stream
        requestCounter += 1
        Console.WriteLine("xml data request at " & DateTime.Now.ToString() & ", request count= " & requestCounter)
        Console.WriteLine(WebOperationContext.Current.IncomingRequest.UserAgent.ToString())
        Return _ReturnXML("<xmlresponse><data><argument1>" & argument1 & "</argument1><argument2>" & argument2 & "</argument2></data><server><serverlivesince>" & serverStart.ToString() & "</serverlivesince><pageservetime>" & DateTime.Now.ToString() & "</pageservetime><requestcount>" & requestCounter & "</requestcount></server></xmlresponse>")
        'returns the first two parameters, and the time and date
    End Function

    Private Shared Function _ReturnXML(_result As String) As Stream
        Dim data = Encoding.UTF8.GetBytes(_result)

        WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml; charset=utf-8"
        WebOperationContext.Current.OutgoingResponse.ContentLength = data.Length

        Return New MemoryStream(data)
    End Function
End Class

然后,我有类似的代码来返回HTML以及接受其他参数组合。

在我的主类中,我实例化并打开了这个服务,如下所示:

代码语言:javascript
复制
Dim varWebService = New WebServiceHost(GetType(MyWebService), New Uri("http://0.0.0.0/"))
varWebService.Open()

有人能为我提供实现这种简单身份验证的代码吗?或者给我指点一个完整的教程?谢谢你的帮助

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-15 14:54:56

您可以通过继承编写一个自定义WebServiceHost,并更改一些默认参数,如下所示。

您代码中唯一的更改将是

代码语言:javascript
复制
Dim varWebService = New AuthenticatedWebServiceHost(GetType(MyWebService), New Uri("http://0.0.0.0/"))

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IdentityModel;
using System.IdentityModel.Selectors;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Security;
using System.ServiceModel.Description;

namespace StackOverflow
{
    public class AuthenticatedWebServiceHost : WebServiceHost
    {
        public AuthenticatedWebServiceHost(Type type, Uri url)
        {
            IDictionary<string, ContractDescription> desc = null;
            base.InitializeDescription(type, new UriSchemeKeyedCollection());
            base.CreateDescription(out desc);
            var val = desc.Values.First();

            WebHttpBinding binding = new WebHttpBinding();
            binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

            base.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
            base.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();

            base.AddServiceEndpoint(val.ContractType, binding, url);
        }

        //Possible next question:
        //"How can I get the name of the authenticated user?"
        public static string UserName
        {
            get
            {
                if (OperationContext.Current == null) return null;
                if (OperationContext.Current.ServiceSecurityContext == null) return null;
                if (OperationContext.Current.ServiceSecurityContext.PrimaryIdentity == null) return null;
                return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
            }
        }



        public class CustomUserNamePasswordValidator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                //Your logic to validate username/password
                if (userName != password)
                    throw new SecurityAccessDeniedException();
            }
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2019-10-01 21:25:14

I4V提供的答案效果很好,转换成VB并复制到下面,以防其他人花了很多时间在网上搜索后需要它。

调用它的行是根据I4V提供的代码。

代码语言:javascript
复制
Dim varWebService = New AuthenticatedWebServiceHost(GetType(MyWebService), New Uri("http://0.0.0.0/"))

VB.Net代码

代码语言:javascript
复制
Imports System.IdentityModel.Selectors
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Security
Imports System.ServiceModel.Web

Public Class AuthenticatedWebServiceHost
    Inherits WebServiceHost

    Public Sub New(ByVal type As Type, ByVal url As Uri)
        Dim desc As IDictionary(Of String, ContractDescription) = Nothing
        MyBase.InitializeDescription(type, New UriSchemeKeyedCollection())
        MyBase.CreateDescription(desc)
        Dim val = desc.Values.First()
        Dim binding As WebHttpBinding = New WebHttpBinding()
        binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic
        MyBase.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom
        MyBase.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = New CustomUserNamePasswordValidator()
        MyBase.AddServiceEndpoint(val.ContractType, binding, url)
    End Sub

    Public Shared ReadOnly Property UserName As String
        Get
            If OperationContext.Current Is Nothing Then Return Nothing
            If OperationContext.Current.ServiceSecurityContext Is Nothing Then Return Nothing
            If OperationContext.Current.ServiceSecurityContext.PrimaryIdentity Is Nothing Then Return Nothing
            Return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name
        End Get
    End Property

    Public Class CustomUserNamePasswordValidator
        Inherits UserNamePasswordValidator

        Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
            If userName <> password Then Throw New SecurityAccessDeniedException()
        End Sub
    End Class
End Class
票数 0
EN

Stack Overflow用户

发布于 2020-06-12 06:57:12

夏伊多,你是最棒的!谢谢!这就是我花了几个星期寻找的!我扩展了vb代码以便将其与https: VB.NET一起使用:

代码语言:javascript
复制
Public Class AuthenticatedWebServiceHost
   Inherits WebServiceHost
    Public Sub New(ByVal type As Type, ByVal url As Uri, MyThumbprint As String)
        Dim desc As IDictionary(Of String, ContractDescription) = Nothing
        MyBase.InitializeDescription(type, New UriSchemeKeyedCollection())
        MyBase.CreateDescription(desc)
        Dim val = desc.Values.First()
        Dim binding As WebHttpBinding = New WebHttpBinding()
        'binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly
        binding.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic
        MyBase.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom
        MyBase.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = New CustomUserNamePasswordValidator()
        MyBase.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, MyThumbprint)
        MyBase.AddServiceEndpoint(val.ContractType, binding, url)
    End Sub

    Public Shared ReadOnly Property UserName As String
        Get
            If OperationContext.Current Is Nothing Then Return Nothing
            If OperationContext.Current.ServiceSecurityContext Is Nothing Then Return Nothing
            If OperationContext.Current.ServiceSecurityContext.PrimaryIdentity Is Nothing Then Return Nothing
            Return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name
        End Get
    End Property

    Public Class CustomUserNamePasswordValidator
        Inherits UserNamePasswordValidator
        Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
            If userName <> password Then
                Console.WriteLine("Error: Access denied")
                Throw New SecurityAccessDeniedException()
            End If
        End Sub
    End Class
End Class
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15915545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档