6

Hiện tại tôi đang phát với ServiceStack và hỗ trợ Authentication and authorization.Dịch vụ Web ServiceStack có xác thực cơ bản và SetCredentials

Làm việc trên (Dịch vụ Web Host ứng dụng) CustomAuthenticationMvc từ Use Cases project và trong khi cố gắng để hiểu làm thế nào các việc chứng thực, tôi đã làm điều này:

public class AppHost : AppHostBase 
{ 
    public AppHost() : base("Basic Authentication Example", 
                 typeof(AppHost).Assembly) { } 

    public override void Configure(Container container) 
    { 
     // register storage for user sessions 
     container.Register<ICacheClient>(new MemoryCacheClient()); 
     container.Register<ISessionFactory>(c => new SessionFactory(
              c.Resolve<ICacheClient>())); 

     //Register AuthFeature with custom user session and Basic auth provider 
     Plugins.Add(new AuthFeature(
      () => new CustomUserSession(), 
      new AuthProvider[] { new BasicAuthProvider() } 
     )); 

     var userRep = new InMemoryAuthRepository(); 
     container.Register<IUserAuthRepository>(userRep); 

     //Add a user for testing purposes 
     string hash; 
     string salt; 
     new SaltedHash().GetHashAndSaltString("test", out hash, out salt); 
     userRep.CreateUserAuth(new UserAuth 
     { 
      Id = 1, 
      DisplayName = "DisplayName", 
      Email = "[email protected]", 
      UserName = "john", 
      FirstName = "FirstName", 
      LastName = "LastName", 
      PasswordHash = hash, 
      Salt = salt, 
     }, "test"); 
    } 
} 

Việc thực hiện dịch vụ là Hello nổi tiếng thế giới một với [Authenticate] thuộc tính áp dụng ngay trên Yêu cầu DTO ...

[Authenticate] 
[Route("/hello")] 
[Route("/hello/{Name}")] 
public class HelloRequest : IReturn<HelloResponse> 
{ 
    public string Name { get; set; } 
} 

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

public class HelloService : IService<HelloRequest> 
{ 
    public object Execute(HelloRequest request) 
    { 
     return new HelloResponse 
     { 
      Result = "Hello, " + request.Name 
     }; 
    } 
} 

Sử dụng một ứng dụng Console như một Client, tôi có mã này:

static void Main(string[] args) 
{ 
    // The host ASP.NET MVC is working OK! When I visit this URL I see the 
    // metadata page. 
    const string BaseUrl = "http://localhost:8088/api"; 

    var restClient = new JsonServiceClient(BaseUrl); 

    restClient.SetCredentials("john", "test"); 

    HelloResponse response = restClient.Get<HelloResponse>("/hello/Leniel"); 

    Console.WriteLine(response.Result); 
} 

Vấn đề ở đây là tôi không nghĩ rằng restClient.SetCredentials("john", "test"); đang làm việc như tôi mong chờ vì cuộc gọi webservice restClient.Get<HelloResponse>("/hello/Leniel"); được ném một ngoại lệ. Tôi thấy rằng tôi đang được chuyển hướng đến trang đăng nhập ... Tôi nghĩ rằng thiết lập các thông tin nó sẽ không sao để gọi dịch vụ web. Nó không phải là trường hợp ở đây.

Tôi đang làm gì sai? Tôi dự định gọi dịch vụ web này từ ứng dụng MonoTouch iOS nơi người dùng sẽ nhập tên người dùng và mật khẩu của mình vào cửa sổ hộp thoại đơn giản, nhưng trước khi thực hiện điều này, tôi muốn làm cho ứng dụng này hoạt động trong ứng dụng giao diện điều khiển đơn giản này.

EDIT 1

Tôi đã thử mã này để gửi yêu cầu auth (như đã thấy trên thread này):

var authResponse = restClient.Send<AuthResponse>(new Auth 
{ 
    UserName = "john", 
    Password = "test", 
    RememberMe = true, 
}); 

nhưng một ngoại lệ được ném:

Loại định nghĩa nên bắt đầu bằng '{', mong muốn loại được sắp xếp theo thứ tự 'AuthResponse', nhận chuỗi bắt đầu bằng:

<head> 

Hình như tôi có một dịch vụ bỏ lỡ được cấu hình bởi vì nó giữ chuyển hướng tôi đến mặc định ASP.NET MVC Login trang (xem ảnh chụp màn hình Fiddler dưới đây). Tôi cũng đã thay đổi đăng ký AuthFeature qua null đến HtmlRedirect.

//Register AuthFeature with custom user session and Basic auth provider 
Plugins.Add(new AuthFeature(
    () => new CustomUserSession(), 
    new AuthProvider[] { new BasicAuthProvider() } 
) { HtmlRedirect = null }); 

EDIT 2

Chơi với Fiddler tôi đã cố gắng thêm một tiêu đề yêu cầu Authorization như mô tả here:

enter image description here

Nhìn vào thanh tra Auth trong Fiddler tôi có thể thấy điều này:

Authorization Header is present: Basic am9objp0ZXN0 
Decoded Username:Password= john:test 

Bây giờ, tại sao tôi nhận được trạng thái trái phép 401?Không nên nó chỉ làm việc cho rằng tôi thiết lập một người sử dụng trong bộ nhớ cho mục đích thử nghiệm?

Làm cách nào để chuyển tiêu đề yêu cầu trong ứng dụng bảng điều khiển mẫu?

Nếu tôi làm trong các ứng dụng giao diện điều khiển:

restClient.AlwaysSendBasicAuthHeader = true; 

tôi nhận được phản ứng trái phép 401 ...

EDIT 3

Với sự giúp đỡ của câu trả lời và mã bổ sung desunit của, Tôi đã quản lý để xác thực ứng dụng Console hoạt động với mã sau:

class Program 
{ 
    const string BaseUrl = "http://localhost:8088/api"; 

    static void Main(string[] args) 
    { 
     var restClient = new JsonServiceClient(BaseUrl); 

     restClient.SetCredentials("john", "test"); 

     restClient.AlwaysSendBasicAuthHeader = true; 

     HelloResponse response = restClient.Get<HelloResponse>("/hello/Leniel"); 

     Console.WriteLine(response.Result); 
    } 
} 

//Response DTO 
//Follows naming convention 
public class HelloResponse 
{ 
    public string Result { get; set; } 
} 

Tôi muốn biết những điều sau đây ngay bây giờ: Trong Ứng dụng Console, tôi có nên luôn luôn gửi Tiêu đề xác thực cơ bản không? Nếu tôi xóa dòng đó, xác thực không thành công và tôi không nhận được số HelloResponse.

Trả lời

4

Sự cố không liên quan đến ServiceStack nhưng cách ASP.NET xử lý mã lỗi 401. Bạn có thể giải quyết sự cố bằng tùy chỉnh IHttpModule ngăn chặn chuyển hướng tới biểu mẫu Đăng nhập. Chi tiết thêm về vấn đề đó có thể được đọc here.

Vì đây là vấn đề khá phổ biến we have updatedCustomAuthenticationMvc dự án để chứng minh giải pháp khả thi.

+0

Khá thú vị ... Tôi vừa tải xuống toàn bộ dự án từ GitHub lần nữa với các bổ sung mới và bây giờ xác thực 'Basic' và' Custom' chỉ hoạt động khi nhấp vào nút 'Gọi bằng AJAX' trong trang Chỉ mục. Vào ngày 1, nó yêu cầu tên người dùng và mật khẩu và những người tiếp theo chỉ cần truy cập trực tiếp vào dịch vụ web. Gỡ lỗi bằng Firebug Tôi có thể thấy tiêu đề Cấp phép và cookie. Tôi chỉ không biết làm thế nào để làm cho tất cả công việc này từ bên trong Console App ... Làm thế nào tôi có thể xác thực trước khi gọi dịch vụ web? –

+0

Nếu tôi đặt 'restClient.AlwaysSendBasicAuthHeader = true;' ngay sau khi thiết lập thông tin đăng nhập với 'restClient.SetCredentials (" john "," test ");' nó chỉ hoạt động. Tại sao? Trong ứng dụng Console nên tôi luôn gửi Tiêu đề xác thực cơ bản? –

+1

Có, chỉ cần kiểm tra SetCredentials một mình nên làm việc như mong đợi. Vấn đề duy nhất mà tôi thấy là JsonServiceClient sẽ không gửi tiêu đề X-Requested-With cho bạn, vì vậy bạn cũng cần kiểm tra AcceptTypes để tránh chuyển hướng. Vui lòng xem [cam kết này] (https://github.com/ServiceStack/ServiceStack.UseCases/commit/97338a21faa4b92302017354e9e9a970b2a671bc) để biết các thay đổi bổ sung này. – desunit