10

Chúng tôi có một ứng dụng sử dụng ASP.net Membership để cung cấp cơ chế đăng nhập cơ bản. Tất cả đều hoạt động tốt, nhưng gần đây chúng tôi phát hiện ra rằng nếu bạn cố truy cập trang đăng nhập khi đăng nhập, bạn sẽ được chuyển hướng đến trang 'Không được phép'.Thành viên ASP.NET Đăng nhập chuyển hướng trái phép khi người dùng đăng nhập

Luồng người dùng mẫu.

Người dùng truy cập trang được bảo mật (toàn bộ ứng dụng yêu cầu đăng nhập, có thậm chí không phải trang chủ bạn có thể truy cập, chỉ chuyển hướng thẳng đến đăng nhập). Điều này chuyển hướng chúng đến https://www.example.com/Account/Login.

Nhật ký người dùng và được chuyển hướng đến trang chủ https://www.example.com/. Chúng được đăng nhập và mọi thứ hoạt động tốt.

Người dùng nhấp bookmark điều đó xảy ra để được thiết lập để https://www.example.com/Account/Login

người dùng được chuyển hướng đến trang generic trái phép.

Tôi có <Authorize()> thuộc tính trên AccountController của tôi nhưng <AllowAnonymous()> thuộc tính về hành động 'Đăng nhập', mà như ta đã biết, hoạt động tốt khi bạn chưa đăng nhập, nhưng khi bạn đang có vẻ như để có được trong một bit của một mớ hỗn độn.

AccountController

<Authorize()> _ 
Public Class AccountController 
'''other functions go here''' 

<AllowAnonymous()> _ 
Public Function Login(ByVal returnUrl As String) As ActionResult 
    ViewData("ReturnUrl") = returnUrl 
    Return View() 
End Function 

lọc AuthorizeRedirect

<AttributeUsage(AttributeTargets.[Class] Or AttributeTargets.Method)> _ 
Public Class AuthorizeRedirect 
    Inherits AuthorizeAttribute 
    Private Const IS_AUTHORIZED As String = "isAuthorized" 

    Public RedirectUrl As String = "~/Home/Unauthorized" 

    Protected Overrides Function AuthorizeCore(httpContext As System.Web.HttpContextBase) As Boolean 
     Dim isAuthorized As Boolean = MyBase.AuthorizeCore(httpContext) 

     httpContext.Items.Add(IS_AUTHORIZED, isAuthorized) 

     Return isAuthorized 
    End Function 

    Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext) 
     MyBase.OnAuthorization(filterContext) 

     Dim isAuthorized = If(filterContext.HttpContext.Items(IS_AUTHORIZED) IsNot Nothing, Convert.ToBoolean(filterContext.HttpContext.Items(IS_AUTHORIZED)), False) 

     If Not isAuthorized AndAlso filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated Then 
      filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl) 
     End If 
    End Sub 
End Class 

Thấy tất cả điều này tôi nghĩ là giải pháp đơn giản nhất sẽ là để kiểm tra xem người dùng đã đăng nhập vào hành động nhập của tôi và chuyển hướng chúng đi, một cái gì đó như thế này.

<AllowAnonymous()> _ 
Public Function Login(ByVal returnUrl As String) As ActionResult 
    If User.Identity.IsAuthenticated() Then 
     Return RedirectToAction("Index", "Home") 
    End If 
    ViewData("ReturnUrl") = returnUrl 
    Return View() 
End Function 

Nhưng AuthorizeFilter luôn nhảy theo cách đầu tiên, điều này là dễ hiểu, nhưng tôi không thể tìm ra phần còn thiếu cuối cùng. Tất cả những gì tôi muốn là nó không hiển thị 'Bạn không có quyền xem trang này' nếu người dùng truy cập vào màn hình đăng nhập khi đăng nhập và chuyển hướng họ đến trang chủ. Tôi đang thiếu gì?


Chỉnh sửa để làm cho mọi việc rõ ràng hơn một chút

Khi đã đăng nhập, tôi đi đến /Account/Login. Điều này 302 chuyển hướng tôi đến /Home/Unauthorized (trang tùy chỉnh của tôi). Tuy nhiên, tôi vẫn đăng nhập.

Mạng yêu cầu

Network request to Login page, which 302 redirects to Unauthorized

trang trái phép. Lưu ý các phần màu vàng được tô sáng cho biết tôi vẫn đang đăng nhập. Điều này chỉ xuất hiện nếu bạn đã đăng nhập. Khi chưa đăng nhập, bạn sẽ không nhận được thông tin nào trong số đó.

Unauthorized page

Vấn đề dường như là ứng dụng không biết phải làm gì khi tôi đã đăng nhập và cố gắng để đi đến một trang mà có [AllowAnonymous] thuộc tính trên đó. Nếu bất cứ điều gì, hành vi tôi thấy ở đây là thích hợp hơn để nó thực sự cho tôi một trang đăng nhập một lần nữa, bởi vì điều đó sẽ gây nhầm lẫn, nhưng vẫn còn, nó không lý tưởng.


Chỉnh sửa 2 - Đẩy mạnh thông qua các dòng mã của dòng

Dưới đây là kết quả của bước qua dòng mã của dòng.

Trang /Account/Login trong khi đăng nhập.

breakpoint đầu tiên trong OnAuthorization phụ trong AuthorizeRedirect lọc.

Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext) 
    MyBase.OnAuthorization(filterContext) 

    Dim isAuthorized = If(filterContext.HttpContext.Items(IS_AUTHORIZED) IsNot Nothing, Convert.ToBoolean(filterContext.HttpContext.Items(IS_AUTHORIZED)), False) 

    If Not isAuthorized AndAlso filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated Then 
     filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl) 
    End If 
End Sub 

Dòng bắt đầu bằng Dim isAuthorized trả về Sai. filterContext.HttpContext.Items(IS_AUTHORIZED) là không có gì (không tồn tại trong danh sách các mục).

Điều này sau đó có nghĩa là câu lệnh If tiếp theo đánh giá là True (Not isAuthorized AndAlso ... IsAuthenticated), dẫn đến chuyển hướng đến RedirectUrl.

Sau khi điều này xảy ra, nó xuất hiện trở lại qua các bước tương tự, ngoại trừ thời gian này nó được đánh giá sai, có nghĩa là chuyển hướng không xảy ra, mặc dù tôi đoán đây chỉ là trang 'Không được phép' tải và chạy qua cùng một mã một lần nữa.

Tôi đã cố gắng thêm khối sau vào đầu chức năng Login của AccountController.

If User.Identity.IsAuthenticated() Then 
     Return RedirectToAction("Index", "Home") 
    End If 

Nhưng, tất nhiên, kể từ khi bộ lọc được thực hiện trước các hành động xảy ra mã này không được đánh cho đến khi sau nó đã chuyển hướng tôi đến Unauthorized (xác nhận qua bước qua).

+0

Áp dụng 'AuthorizeRedirect' ở đâu? –

+0

Không có quyền truy cập vào mã bây giờ, nhưng tôi khá chắc chắn rằng nó được thiết lập trong tiêu chuẩn FilterConfig với một cái gì đó như 'filters.add (Authorizeredirect)' –

+0

dường như người dùng đang bị trái phép. Điều đó có đúng không? bạn có thể nhấn/home/index sau khi được chuyển hướng sang trái phép không? –

Trả lời

2

Các lớp cơ sở cho AuthorizationAttribute có mã này trong phương pháp OnAuthorization của nó:

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true) 
         || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true); 

if (skipAuthorization) 
{ 
    return; 
} 

if (AuthorizeCore(filterContext.HttpContext)) 
// ... 

Như vậy nếu hành động điều khiển có một định nghĩa AllowAnonymousAttribute khi đó, phương pháp AuthorizeCore của bạn sẽ không được gọi.

Do đó filterContext.HttpContext.Items(IS_AUTHORIZED) sẽ không bao giờ được đặt.

Bạn chỉ cần sao chép mã từ here để triển khai OnAuthorization mà không cần gọi lớp cơ sở. Bằng cách này bạn có thể đối phó với bộ nhớ đệm trong đó bao giờ cách bạn muốn.

Ngẫu nhiên, tôi đã bị ấn tượng rằng nếu ủy quyền không thành công thì quy trình sau trong đường dẫn yêu cầu đã chuyển hướng đến trang đăng nhập. Đây là lý do tại sao việc triển khai cơ sở OnAuthorization đặt filterContext.Result thành phiên bản HttpUnauthorizedResult mới. Vì vậy, nó không phải là hoàn toàn rõ ràng lý do tại sao bạn đang ghi đè OnAuthorization và làm chuyển hướng ở nơi đầu tiên.Nếu bạn muốn một số loại mã ủy quyền tùy chỉnh, chỉ cần trả lại true hoặc false từ AuthorizeCore phải là đủ.

Các vấn đề liên quan