2011-03-15 41 views
8

Tôi đã tìm thấy câu trả lời tuyệt vời về SO mô tả how to set up custom user roles và tôi đã thực hiện tương tự trong dự án của mình. Vì vậy, trong dịch vụ đăng nhập của tôi, tôi có:Người dùng có vai trò là "quản trị" nhưng [Ủy quyền (Vai trò = "quản trị")] sẽ không xác thực

public ActionResult Login() { 
    // password authentication stuff omitted here 
    var roles = GetRoles(user.Type); // returns a string e.g. "admin,user" 
    var authTicket = new FormsAuthenticationTicket(
        1, 
        userName, 
        DateTime.Now, 
        DateTime.Now.AddMinutes(20), // expiry 
        false, 
        roles, 
        "/"); 
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
    FormsAuthentication.Encrypt(authTicket)); 
    Response.Cookies.Add(cookie); 
    return new XmlResult(xmlDoc); // don't worry so much about this - returns XML as ActionResult 
} 

Và trong Global.asax.cs, tôi đã (sao chép nguyên văn từ câu trả lời khác):

protected void Application_AuthenticateRequest(Object sender, EventArgs e) { 
    var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (authCookie != null) { 
    var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
    var roles = authTicket.UserData.Split(new Char[] { ',' }); 
    var userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles); 
    Context.User = userPrincipal; 
    } 
} 

Sau đó, trong lớp ServicesController tôi, tôi có :

[Authorize(Roles = "admin")] 
//[Authorize] 
public ActionResult DoAdminStuff() { 
    ... 
} 

Tôi đăng nhập với tư cách người dùng có vai trò "quản trị" và hoạt động. Sau đó, tôi gọi/services/doadminstuff - và tôi bị truy cập bị từ chối, mặc dù khi tôi đặt một breakpoint trong Global.asax.cs, tôi có thể thấy rằng vai trò của tôi có bao gồm "admin". Nếu tôi nhận xét thuộc tính Authorize đầu tiên (có vai trò) và chỉ cần sử dụng vanilla đơn giản Authorize thì tôi có thể truy cập dịch vụ.

Tôi phải thiếu thứ gì đó quan trọng ở đây - nhưng phải bắt đầu từ đâu?

Trả lời

15

tôi sẽ khuyên bạn sử dụng một thuộc tính tùy chỉnh ủy quyền thay vì Application_AuthenticateRequest:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     string cookieName = FormsAuthentication.FormsCookieName; 

     if (!filterContext.HttpContext.User.Identity.IsAuthenticated || 
      filterContext.HttpContext.Request.Cookies == null || 
      filterContext.HttpContext.Request.Cookies[cookieName] == null 
     ) 
     { 
      HandleUnauthorizedRequest(filterContext); 
      return; 
     } 

     var authCookie = filterContext.HttpContext.Request.Cookies[cookieName]; 
     var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
     string[] roles = authTicket.UserData.Split(','); 

     var userIdentity = new GenericIdentity(authTicket.Name); 
     var userPrincipal = new GenericPrincipal(userIdentity, roles); 

     filterContext.HttpContext.User = userPrincipal; 
     base.OnAuthorization(filterContext); 
    } 
} 

và sau đó:

[CustomAuthorize(Roles = "admin")] 
public ActionResult DoAdminStuff() 
{ 
    ... 
} 

Cũng là một điều rất quan trọng là phải đảm bảo rằng khi bạn đăng nhập một cookie xác thực là được phát ra bởi vì bạn trả về một tệp XML. Sử dụng FireBug để kiểm tra xem cookie xác thực có được gửi đúng cách không khi bạn cố gắng truy cập url /services/doadminstuff.

+3

Đã hoạt động! CẢM ƠN BẠN! Nói cho tôi biết, tại sao công việc này lại có tác dụng, nhưng cái ở Global.asax.cs thì không? –

+1

Cảm ơn bạn lần nữa vì đã giúp đỡ! Có lẽ bạn cũng có thể làm sáng tỏ một số vấn đề liên quan này: http://stackoverflow.com/q/6586156/7850 –

+0

cảm ơn, nó hoạt động. và làm thế nào tôi có thể kiểm soát thêm trang nào để hiển thị và với thông điệp chính xác. – Timeless

0

tôi sẽ thay đổi assign chính lúc đầu:

Thread.CurrentPrincipal = userPrincipal; 
if (HttpContext.Current != null) 
{ 
    HttpContext.Current.User = userPrincipal; 
} 

như ASP.NET tài liệu đứng.

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