【问题标题】:Why is my self-hosted WCF service returning 403 Forbidden, rather than 401 Unauthorized?为什么我的自托管 WCF 服务返回 403 Forbidden,而不是 401 Unauthorized?
【发布时间】:2012-09-07 09:20:00
【问题描述】:

我一直在尝试使用 WCF 创建一个相对简单的自托管 RESTful 服务,但我想添加自定义身份验证。为此,我尝试覆盖UserNamePasswordValidator。不幸的是,尽管调用它来验证用户名/密码组合,但如果用户名/密码不通过,服务器将返回 403 Forbidden,而不是 401 Unauthorized,正如我所期望的那样。这将导致一个大问题,因为如果用户第一次验证失败,除非他们重新启动浏览器,否则不会提示他们再次输入凭据。那么,我做错了什么?

这是我目前所拥有的:

(实际的ServiceContract 包含一个返回字符串的方法)

class Program
{
    static void Main(string[] args)
    {
        WebServiceHost host = null;
        try
        {
            host = new WebServiceHost(typeof (MyService));
            const string uri = "http://127.0.0.1/MyService";
            var wb = new WebHttpBinding
                            {
                                Security =
                                    {
                                        Mode = WebHttpSecurityMode.TransportCredentialOnly,
                                        Transport = {ClientCredentialType = HttpClientCredentialType.Basic}
                                    }
                            };
            var ep = host.AddServiceEndpoint(typeof (IMyService), wb, uri);
            host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
            host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new PasswordValidator();
            host.Open();

            Console.WriteLine("Press any key to terminate");
            Console.ReadKey();
        }
        finally
        {
            if (host != null) host.Close();
        }
    }
}

public class PasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        if (null == userName || null == password)
            throw new ArgumentNullException();

        if (userName == "Test" && password == "Password") return;
        throw new WebFaultException(HttpStatusCode.Unauthorized);
    }
}

我已经注意到这个other, similar question,但是那里发布的答案都没有真正起作用。我希望这个问题的更完整定义的版本会引起更好的回答。

【问题讨论】:

  • 它并不完全有帮助,但它确实提供了精神上的支持和解释:)
  • 实际上,我收回了这一点,我没有读到足够远的内容,看不到那里有解决方案,与在这个问题上发布和接受的解决方案相同。

标签: c# wcf


【解决方案1】:

试试这个:

public override void Validate(string userName, string password) 
{ 
    if (null == userName || null == password)             
        throw new ArgumentNullException(); 
    if (userName == "Test" || password == "Password") return; 

    WebFaultException rejectEx = new WebFaultException(HttpStatusCode.Unauthorized);
    rejectEx.Data.Add("HttpStatusCode", rejectEx.StatusCode);
    throw rejectEx;
} 

据我所知,这是一种未记录的技术,它依赖于 WCF 堆栈如何在内部管理异常。应该有记录的方式,但我还没有找到。

【讨论】:

  • 你是从哪里发现这个的? :) 它有效,但它让我开始思考我现在是否真的想使用 WCF...
  • 虽然这可行,但它会导致您的函数 Validate 被调用两次。返回 SecurityTokenException 只会调用一次。用 HttpWebRequest 测试
猜你喜欢
  • 1970-01-01
  • 2023-01-20
  • 2012-11-01
  • 2011-03-18
  • 2011-02-01
  • 2017-05-15
  • 2020-04-17
  • 2013-03-10
相关资源
最近更新 更多