11

tôi đang làm việc trên dự án ASP.NET MVC5 trong đó có hình thức xác thực được kích hoạt. Dự án hiện đang trong giai đoạn thử nghiệm, và lưu trữ trực tuyến trên Azure, nhưng chủ dự án muốn vô hiệu hóa tất cả các truy cập công cộng vào trang web (vì một số phần của trang web không yêu cầu cho người sử dụng để xác thực ở tất cả).ASP.NET MVC5 Basic xác thực HTTP và AntiForgeryToken ngoại lệ

Đối với giai đoạn thử nghiệm này, chúng tôi đã quyết định để thực hiện xác thực HTTP cơ bản, từ link này. Tôi đã thay đổi mã, do đó phù hợp hơn với nhu cầu của tôi:

public class BasicAuthenticationAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    public string BasicRealm { get; set; } 

    protected string Username { get; set; } 
    protected string Password { get; set; } 

    public BasicAuthenticationAttribute(string username, string password) 
    { 
     this.Username = username; 
     this.Password = password; 
    } 

    public void OnAuthorization (AuthorizationContext filterContext) 
    { 
     var req = filterContext.HttpContext.Request; 
     var auth = req.Headers["Authorization"]; 
     if (!String.IsNullOrEmpty(auth)) 
     { 
      var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':'); 
      var user = new { Name = cred[0], Pass = cred[1] }; 

      if (user.Name == Username && user.Pass == Password) 
       return; 
     } 

     var res = filterContext.HttpContext.Response; 
     var alreadySent = HttpContext.Current.Items.Contains("headers-sent"); 

     if (!alreadySent) 
     { 
      res = filterContext.HttpContext.Response; 
      res.StatusCode = 401; 
      res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 

     } 
    } 
} 

Tôi cũng đã đăng ký nó như một bộ lọc toàn cầu:

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorExtendedAttribute()); 
     filters.Add(new BasicAuthenticationAttribute(AppConfig.BasicUsername, AppConfig.BasicPassword)); 
    } 
} 

Tuy nhiên, có một số vấn đề khi tôi chạy dự án . Nếu tôi sử dụng phiên bản mã này:

 if (!alreadySent) 
     { 
      res = filterContext.HttpContext.Response; 
      res.StatusCode = 401; 
      res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 
     } 

sau khi đăng nhập thành công, nó liên tục chuyển hướng đến trang đăng nhập biểu mẫu.

Tuy nhiên nếu tôi thêm

res.End(); 

sau

res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 

Antiforgerytoken trong các tập tin cshtml ném System.Web.HttpException

Server không thể thêm tiêu đề sau khi tiêu đề HTTP đã gởi.

Nhưng trong trường hợp này, cuối cùng xác thực thành công.

Tôi hiện đang bị mắc kẹt về vấn đề này và không biết cách giải quyết vấn đề này vì việc tắt xác thực biểu mẫu không phải là tùy chọn và tôi không thể xóa tất cả AntiForgeryTokens và xác thực của chúng.

+2

Tại sao bạn chọn phương pháp này?Nếu bạn muốn xây dựng một 'Bộ lọc xác thực 'tùy chỉnh, bạn nên kế thừa từ' AuthorizeAttribute', ghi đè hàm 'IsAuthorized', trả về' false' cho các yêu cầu trái phép và xử lý chúng trong hàm 'HandleUnauthorizedRequest'. – AnhTriet

+0

Nếu bạn lật res.StatusCode dòng với res.AppendHeader dòng những gì sẽ xảy ra? Giá trị StatusCode có được tính là một phần của "Nội dung" để đóng các Tiêu đề không được viết nữa không? Ngoài ra xin vui lòng xem xét phản ứng của Andrew dưới đây. –

+0

plz không sử dụng auth cơ bản. Lưu ý rằng câu hỏi khác mà bạn tham khảo giống như 6 tuổi, và thậm chí sau đó đã có lựa chọn thay thế tốt hơn. Xem: http://adrianotto.com/2013/02/why-http-basic-auth-is-bad/ – nothingisnecessary

Trả lời

1

Các bạn đã thử dòng này trước khi res.AppendHeader (..)?

Response.ClearHeaders(); 
3

tôi sẽ đề nghị bạn sử dụng nhà cung cấp thành viên ASP.NET nhận dạng vì nó được bao gồm trong MVC 5. Sử dụng này, bạn có thể dễ dàng xác thực người dùng mà không cần viết nhiều mã như nó đã được với thành viên trước. Nó cũng có thể sử dụng đăng nhập bên ngoài với các cookie nội bộ như thể bạn sử dụng phương thức FormsAuthentication. Tất cả những gì bạn cần là làm cho cấu hình đơn giản trong mã và bạn không cần phải viết bộ lọc tùy chỉnh của bạn.

1

Thay vì kết thúc yêu cầu với req.End(), tôi nghĩ bạn muốn đặt filterContext.Result như được hiển thị bên dưới. Thiết lập các kết quả đến một giá trị không null sẽ làm gián đoạn quá trình xử lý phần còn lại của các đường ống dẫn MVC và gây ra các phản ứng sẽ được gửi đến trình duyệt, nhưng nó không nên niêm phong các phản ứng như End() không, vì vậy bạn không nên có được ngoại lệ về tiêu đề đã được gửi.

Hãy thử điều này:

filterContext.Result = new HttpUnauthorizedResult(); 
Các vấn đề liên quan