2013-12-17 14 views
8

Tôi đã bắt đầu một trang web MVC 5 mới, sử dụng Asp.Net Identity mới với Owin. Trong bộ điều khiển "tài khoản" của tôi có thuộc tính [Authorize], tôi có các hành động khá chuẩn;Cách chuyển hướng đến returnUrl hoạt động trong Asp.Net MVC5

// GET: /User/Login 
     [AllowAnonymous] 
     public ActionResult Login(string returnUrl) 
     { 
      ViewBag.ReturnUrl = returnUrl; 
      return View(); 
     } 

// POST: /User/Login 
     [HttpPost] 
     [AllowAnonymous] 
     [ValidateAntiForgeryToken] 
     public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
     { 
      try 
      { 
       if (ModelState.IsValid) 
       { 
        var userApi = new UserService(); 
        var apiUser = await userApi.LogIn(UserManager, model.CardNumber, model.Pin, model.RememberMe); 

        if (apiUser != null) 
        { 
         await SignInAsync(apiUser, model.RememberMe); 
         if (string.IsNullOrEmpty(returnUrl)) 
         {         
          return RedirectToAction("UserLoggedIn", "User");  
         } 
        } 
        else 
        { 
         ModelState.AddModelError("", "Invalid username or password."); 
        } 
       } 

      } 
      catch (Exception ex) 
      { 
       Trace.TraceError("Cannot login {0}", ex.ToString()); 
       Response.AppendToLog(ex.ToString()); 
       ModelState.AddModelError("", ex.ToString()); 
      } 
      // If we got this far, something failed, redisplay form 
      return View(model); 
     } 

Câu hỏi của tôi là liên quan đến các hành vi ReturnURL, các mã trên hoạt động trong ý nghĩa đó, nếu người dùng không đăng nhập và kêu gọi một hành động trong một bộ điều khiển có thuộc tính [Duyệt], nó được được gửi đến các hành động đăng nhập ở trên và sau đó quay lại bộ điều khiển/hành động đã được yêu cầu. Đó là tuyệt vời, NHƯNG làm thế nào ?? Và nó có an toàn không?

Trong bài viết này về "Preventing open redirect attacks" (đối với phiên bản trước của Asp.Net MVC) đề xuất là thực hiện kiểm tra trên returnUrl rằng đó là url cục bộ trước khi thực hiện chuyển hướng, đó là điều tôi vẫn nên làm hoặc là nó bây giờ được xử lý bởi khuôn khổ?

Chúc mừng, Ola

Trả lời

13

Bạn cần phải kiểm tra nếu url là địa phương thực sự sử dụng phương pháp này (nó không được xử lý bởi khuôn khổ tự động): http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.islocalurl%28v=vs.118%29.aspx

if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)) 
{ 
    return Redirect(returnUrl); 
} 
+0

Bạn có bất cứ nguồn cho các thông tin mà nó không được xử lý? Có vẻ lạ rằng họ sẽ đưa vào các chức năng để chuyển hướng đến returnUrl tự động nhưng không làm theo hướng dẫn riêng của họ khi làm như vậy. Do đó câu hỏi ban đầu. –

+0

Tại sao bạn không cố gắng thao tác returnUrl và xem điều gì sẽ xảy ra? Nhân tiện, trong mã của bạn, đối số 'returnUrl' không bao giờ được sử dụng. – Marthijn

+0

Vâng tôi đoán đó sẽ là một lựa chọn. Tôi biết returnUrl không bao giờ được sử dụng trong hành động của tôi, nhưng trang web vẫn chuyển hướng chính xác, đó là lý do tại sao tôi tự hỏi nó hoạt động như thế nào, ma thuật hay chỉ là điều gì đó xảy ra để xếp hàng? Hay là họ đã thêm hỗ trợ tự động cho thứ đó? –

3
 if (Url.IsLocalUrl(returnUrl)) 
     { 
      return Redirect(returnUrl); 
     } 
     else 
     { 
      return RedirectToAction("Index", "Controller"); 
     } 
+0

Tôi biết mã này, các câu hỏi là nếu tôi cần phải sử dụng nó hoặc nếu điều này được xử lý trong khuôn khổ cho MVC5 –

2

Để trả lời của bạn câu hỏi đầu tiên về cách Url chuyển hướng được thiết lập, nó được cấu hình trong Startup.Auth.cs được gọi là từ Startup.cs và được đánh dấu bằng thuộc tính có thể được tìm kiếm bởi khung OWIN trên khởi động ứng dụng và bo th tập tin partial mở rộng một lớp Startup.

Trong Startup.Auth.cs có một lớp học để cấu hình tùy chọn xác thực và thường có đoạn mã sau

public partial class Startup 
{ 
    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864 
    public void ConfigureAuth(IAppBuilder app) 
    { 
     // Enable the application to use a cookie to store information for the signed in user 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString("/Account/Login"), 
      CookieSecure = CookieSecureOption.Always 
     }); 
     // Use a cookie to temporarily store information about a user logging in with a third party login provider 
     app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

     // .... 
     // I deleted code which is commented out if you selected "Individual accounts" 
     // if you created the site project using the VS 2013 wizard 
     // ... 
    } 
} 

tôi thêm CookieSecure tùy chọn để đảm bảo các tập tin cookie đã được ký kết và được khuyến cáo như là một thực tế an ninh tốt, ngoại trừ rằng nó mã tấm nồi hơi.

Tài liệu khác trên CookieAuthenticationOptions nếu bạn muốn.

+1

Nếu toàn bộ trang web của bạn ở dạng HTTPS, thì không cần sử dụng 'CookieSecureOption.Always'. Bên cạnh đó, từ tài liệu, điều này cũng buộc bạn phải sử dụng HTTPS để phát triển địa phương. Theo mặc định, nó là 'CookieSecureOption.SameAsRequest'. Vì vậy, nếu trang web của bạn ở dạng HTTPS, bạn không nên thay đổi thuộc tính 'CookieSecure' vì cài đặt mặc định đủ an toàn. – QuantumHive

2

Như Sandeep Phadke đã nói, tham số returnUrl được điền, vì cấu hình trong startup.Auth.cs.

CookieAuthenticationOptions có thuộc tính ReturnUrlParameter được đặt theo Mặc định thành "returnUrl". Đó là lý do, tại sao nó trông giống như ma thuật. Bạn có thể thay đổi nó để bất cứ điều gì bạn muốn:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
    { 
     AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
     LoginPath = new PathString("/Account/Login"), 
     ReturnUrlParameter = "returnTo" 
    }); 

Sau đó, bạn có thể thay đổi các AccountController Login-Hành động:

[AllowAnonymous] 
    public ActionResult Login(string returnTo) 
    { 
     ViewBag.ReturnUrl = returnTo; 
     return View(); 
    } 
Các vấn đề liên quan