在自定义ActionFilterAttribute中访问自定义主体

我正在研究ASP.NET MVC应用程序。 我已经实施了自定义会员提供者,委托人和身份。 在自定义提供程序中,我将ValidateUser()方法中的HttpContext.Current.User替换为:

public sealed class CustomMembershipProvider : MembershipProvider {  
    ...  
    public override bool ValidateUser(string username, string password) {  
      ...  
      CustomIdentity identity = new CustomIdentity(...);  
      CustomPrincipal cu = new CustomPrincipal(identity);  
      HttpContext.Current.User = cu;  
      ...  
    }  
    ...  
}

在AccountController(调用自定义成员资格提供程序)中,我可以按如下方式访问自定义标识:

public class AccountController : BaseController {  
  ...  
  public ActionResult LogOn(string userName,   
                            string password,   
                            bool rememberMe,   
                            string returnUrl) {  
    ...  
    CustomIdentity ci = (CustomIdentity)HttpContext.User.Identity;  
    ...  
  }  
  ...  
}

我的所有控制器继承调用自定义属性的BaseController,如下所示:

[CustomAttribute]  
public abstract class BaseController : Controller {  
  ...  
}  

我想让其他控制器在按照以下方式设置AccountController后访问自定义属性中的自定义标识:

public class CustomAttribute : ActionFilterAttribute {  
  public override void OnActionExecuting(ActionExecutingContext filterContext) {  
    base.OnActionExecuting(filterContext);  
    CustomIdentity ci = filterContext.HttpContext.User.Identity as CustomIdentity;  
    ...  
    }  
  }  
}  

我发现的是,filterContext.HttpContext.User仍然设置为GenericPrincipal而不是我的CustomPrincipal。 所以我的自定义身份无法在我的属性过滤器中访问。 我必须做些什么才能在我的属性过滤器中访问我的CustomPrincipal?

提前致谢。


在研究了如何触发应用程序请求事件(特定顺序)以及何时可以设置上下文对象之后,我可以设置自定义主体和身份,以便它们可用于筛选器(贯穿整个应用程序)。

我意识到用户必须经过认证,然后才能将这些实体设置为通过应用程序的其余部分使用。 我发现,这可以在global.asax的Application_AuthenticateRequest()方法中完成。

所以,我修改了我的逻辑如下:

  • 从自定义提供程序的ValidateUser()方法中删除了创建自定义主体和标识。
  • 相反,根据自定义存储库验证用户名和密码后,ValidateUser()会使用用户名作为唯一键在HttpContext.Current.Cache中缓存所需的任何信息。
  • 最后,我在Application_AuthenticateRequest()中添加了以下逻辑,通过提取通用标识属性并使用存储在缓存中的自定义属性扩展它来设置我的自定义主体和标识。 我使用存储在通用标识中的名称将索引编入缓存,因为这是我用来创建缓存的密钥。
    protected void Application_AuthenticateRequest(object sender, EventArgs e) {  
    
      if (Request.IsAuthenticated) {  
    
        // TODO: Add checks so we only do the following once per login.
    
        // Get the GenericPrincipal identity  
        IIdentity ui = HttpContext.Current.User.Identity;  
    
        /* Extract Name, isAuthenticated, AuthenticationType from
           the identity of the GenericPrincipal and add them including 
           any custom properties to the custom identity. I added a 
           few extra properties to my custom identity. */
    
        CustomIdentity identity = new CustomIdentity(...);
    
        /* Although my custom principal does not currently 
           have any additional properties, I created a new  
           principal as I plan to add them in the future. */
    
        CustomPrincipal principal = new CustomPrincipal(identity);
    
        // Set custom principal 
        HttpContext.Current.User = principal;
    
      }
    }
    

    这让我越过了我的障碍。 如果还有其他更好的方法来实现这个目标,请指导我。

    谢谢。


    我不知道这是否是“更好”的方式,但迄今为止它对我有用。 我创建了一个具有CurrentUser属性的静态UserContext类。 在那里我存储从数据库获得的用户实体,并将其用于用户信息数据和授权。 我只使用HttpContext.Current.User来检查身份验证。

    现在, CurrentUser属性将我的用户对象存储在HttpContextItems colletion中(我有一个包装器,所以我可以使它成为单元测试)。

    链接地址: http://www.djcxy.com/p/56575.html

    上一篇: Accessing custom principal within a custom ActionFilterAttribute

    下一篇: Which java socket threw the Connection reset IOException?