1

我正在尝试按照本教程使用我的 ServiceStack 服务设置身份验证。

我的服务用[Authenticate]属性装饰。

我的 AppHost 看起来像这样:

public class TestAppHost : AppHostHttpListenerBase
{
    public TestAppHost() : base("TestService", typeof(TestService).Assembly) { }

    public static void ConfigureAppHost(IAppHost host, Container container)
    {
        try
        {
            // Set JSON web services to return idiomatic JSON camelCase properties.
            ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

            // Configure the IOC container
            IoC.Configure(container);

            // Configure ServiceStack authentication to use our custom authentication providers.
            var appSettings = new AppSettings();
            host.Plugins.Add(new AuthFeature(() =>
                new AuthUserSession(),  // use ServiceStack's session class but fill it with our own data using our own auth service provider
                new IAuthProvider[] { 
                    new UserCredentialsAuthProvider(appSettings)
                }));
        }
   }

UserCredentialsAuthProvider我的自定义凭据提供程序在哪里:

public class UserCredentialsAuthProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        try
        {
            // Authenticate the user.
            var userRepo = authService.TryResolve<IUserRepository>();
            var user = userRepo.Authenticate(userName, password);

            // Populate session properties.
            var session = authService.GetSession();
            session.IsAuthenticated = true;
            session.CreatedAt = DateTime.UtcNow;
            session.DisplayName = user.FullName;
            session.UserAuthName = session.UserName = user.Username;
            session.UserAuthId = user.ID.ToString();
        }
        catch (Exception ex)
        {
            // ... Log exception ...
            return false;
        }
        return true;
    }
}

在我的用户测试中,我初始化并启动我的 TestAppHost on http://127.0.0.1:8888,然后使用 JsonServiceClient 对服务进行身份验证,如下所示:

var client = new JsonServiceClient("http://127.0.0.1:8888/")
var response = client.Send<AuthResponse>(new Auth 
{ 
    provider = UserCredentialsAuthProvider.Name,
    UserName = username, 
    Password = password,
    RememberMe = true
});

但得到以下异常:

The remote server returned an error: (400) Bad Request.
   at System.Net.HttpWebRequest.GetResponse()
   at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](Object request)...

ServiceStack.ServiceInterface.Auth.Auth请求包含正确的用户名和密码,并且该请求被发布到:

http://127.0.0.1:8888/json/syncreply/Auth

我不确定为什么 URL 不是/json/auth/credentials或我可能做错了什么。有什么建议么?


更新

跟踪堆栈中的事件链,我发现以下内容:

JsonDataContractSerializer.SerializeToStream将 Auth 请求正确序列化为 Json。但是,System.Net.HttpRequestStream传递给JsonDataContractDeserializerbyEndpointHandlerBase具有正确长度的流,其中填充了空值(零字节)。结果,传递给的请求对象CredentialsAuthProvider.Authenticate的所有属性都为空。

HTTP 流如何去除其数据?

4

1 回答 1

1

知道了!!!

问题是我为记录目的添加的以下预请求过滤器TestAppHost.Configure

        PreRequestFilters.Add((httpReq, httpRes) =>
        {
            LastRequestBody = httpReq.GetRawBody();
        });

如此处所见。

当该GetRawBody()方法读取请求 InputStream 时,它会将其留在 EOS 状态,并且所有后续读取尝试均不返回任何内容。

所以显然GetRawBody()只能安全地与缓冲流一起使用,但不幸的是它悄悄地导致了一个非常讨厌的错误,而不是在与非缓冲流一起使用时抛出异常。

于 2013-07-09T17:13:54.207 回答