1

I'm trying to create a simple web service with ServiceStack. On the server (service) side, I've first created a user "administrator" and assigned it the "Admin" role. I'm using the ServiceStack built-in credentials authentication and I it authenticates nicely. However, any subsequent call to any webservice that is decorated with the [Authenticate] attribute returns a the following error:

No configuration was added for OAuth provider 'basic'

FYI: the database is RavenDb - using ServiceStack.Authentication.RavenDb. I also registered a MemoryCacheClient in the App_Start.AppHost.Configure(). Let me know if you need to see all code in App_Start.AppHost class.

Server Code (excerpt):

namespace MyTest 
{
    [Route("/hello")]
    [Route("/hello/{Name}")]
    [Authenticate]
    public class Hello
    {
        public string Name { get; set; }
    }

    public class HelloResponse
    {
        public string Result { get; set; }
    }

    public class HelloService : Service
    {
        public IUserAuthRepository UserAuthRepo { get; set; }

        public object Any(Hello request)
        {
            return new HelloResponse { Result = "Hello, " + request.Name };
        }
    }
}

Client side:

var client = new JsonServiceClient("http://127.0.0.1:65385/auth/credentials?format=json");
var auth   = new Auth { UserName = "administrator", Password = "12345" };

var authResponse = client.Post(auth);

if (authResponse.ResponseStatus.ErrorCode == null)
{
    client = new JsonServiceClient("http://127.0.0.1:65385/hello");
    client.UserName = "administrator";
    client.Password = "12345";

    // When sending the request - it returns "Not Found"
    var helloResponse = client.Send(new Hello { Name = "John" });
}

EDIT:
The web.config of my services looks exactly like written in section 2a of the Hello World tutorial

Here's the configuration of my AppHost:

public override void Configure(Funq.Container container)
{
    container.Register(new MemoryCacheClient { FlushOnDispose = false });
    container.Register(new EmbeddableDocumentStore { DataDirectory = "Data" }.Initialize());

    ConfigureAuth(container);
}

private void ConfigureAuth(Funq.Container container)
{
    var appSettings = new AppSettings();

    Plugins.Add(new AuthFeature(() => new CustomUserSession(),
        new IAuthProvider[] {
            new CredentialsAuthProvider(appSettings)}));

    Plugins.Add(new RegistrationFeature());

    container.Register(
        new RavenUserAuthRepository(c.Resolve()));
}
4

3 回答 3

1

Firstly you should look at ServiceStack's AuthTests for some examples that test authentication with ServiceStack's C# Service Clients.

You're passing the wrong urls in your C# ServiceStack client, i.e. you should only pass in the Base URI where ServiceStack is hosted, e.g:

var client = new JsonServiceClient(
    "http://127.0.0.1:65385/auth/credentials?format=json");
var client = new JsonServiceClient("http://127.0.0.1:65385/hello");

Should instead only be:

var client = new JsonServiceClient("http://127.0.0.1:65385/");
var client = new JsonServiceClient("http://127.0.0.1:65385/");

You should also never put ?format=json when using a ServiceStack C# ServiceClient like JsonServiceClient, since the format is already implied in the client which ensures JSON is returned by sending the Accept: application/json HTTP Header upon every request.

于 2013-02-13T05:29:44.813 回答
1

OK, found out what the problem was: The [Authenticate], [RequiredRole] and [RequiredPermission] attributes work with Basic Authentication (Authenticate works with Digest Authentication as well). So if you want to use any of those attributes, you must make sure that you have added the BasicAuthProvider to the list of IAuthProviders when setting up the AuthFeature as a plugin. So,

Plugins.Add(new AuthFeature(() => new CustomUserSession(),
    new IAuthProvider[] {
        new CredentialsAuthProvider(appSettings)}));

must be

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[] {
        new CredentialsAuthProvider(appSettings),
        new BasicAuthProvider() 
    }));

I still have to send username and password in clear text with every call though ...

于 2013-02-13T13:32:32.107 回答
0

Make sure you register an ICacheClient in your ServiceStack application and then you shouldn't have to send the user name and password with each request. Your client side should be able to handle storing a cookie without any effort on your end.

于 2013-03-11T01:44:07.880 回答