替换动作过滤器中的参数

本文关键字:参数 过滤器 替换 | 更新日期: 2023-09-27 18:15:28

我试图从我的动作过滤器中删除参数中捕获的密码,并将其替换为单词"已删除",以便将参数存储在数据库中进行日志记录。密码存储在ViewModel中(取决于操作)。下面是我想要达到的"伪代码"。

我该如何屏蔽/替换要保存在数据库中的密码?我遇到的主要问题是我不知道如何访问密码参数并更改它。我曾尝试使用actionParams.TryGetValue("model, out value)获得它,但问题是,我不知道值的类型,它根据行动而变化。此外,我无法调用actionParams["model"]上的许多方法(如contains)

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var actionParam = filterContext.ActionParameters;
        // Remove the password from the parameters
        if (actionParam.ContainsKey("model") && actionParam["model"] != null)
        {           
            // If actionParam["model"].ToLower().Contains("password")
            // actionParam["model"]["password"] = "Removed";
            // If actionParam["model"].ToLower().Contains("confirm password")
            // actionParam["model"]["confirm password"] = "Removed";
        }
        string str = Json.Encode(filterContext.ActionParameters).Trim();
        string par = string.Empty;
        if (str.Length > 2)
        {
            par = str.Substring(1, str.Length - 2).Replace("'"", string.Empty);
        }
        ActionLog log = new ActionLog()
        {
            SessionId = filterContext.HttpContext.Session.SessionID,
            UserName = (request.IsAuthenticated) ? filterContext.HttpContext.User.Identity.Name : "Anonymous",
            Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
            Action = filterContext.ActionDescriptor.ActionName,
            ActionParameters = par,
            IsPost = request.HttpMethod.ToLower() == "post" ? true : false,
            IPAddress = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress,
            UserAgent = request.UserAgent,
            ActionDate = filterContext.HttpContext.Timestamp
        };
         //Store the Audit into the Database
        ActionLogContext context = new ActionLogContext();
        context.ActionLogs.Add(log);
        context.SaveChanges();
        // Finishes executing the Action as normal
        base.OnActionExecuting(filterContext);
    }

可能的视图模型示例

public class LoginViewModel
{
    [Required]
    [Display(Name = "User ID")]
    [RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage="Letters and Numbers Only")]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }
}
public class ResetPasswordViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }
    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }
    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
    public string Code { get; set; }
}

可能的动作参数示例

        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)

替换动作过滤器中的参数

一种方法是使用接口作为抽象,这样您就不会直接处理ViewModel。首先,创建一些接口,让动作过滤器与之交互。

public interface IPassword
{
    string Password { get; set; }
}
public interface IConfirmPassword
{
    string ConfirmPassword { get; set; }
}

接下来,让你的ViewModel类实现那些接口。

public class LoginViewModel : IPassword
{
    [Required]
    [Display(Name = "User ID")]
    [RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "Letters and Numbers Only")]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }
}
public class ResetPasswordViewModel : IPassword, IConfirmPassword
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }
    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }
    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
    public string Code { get; set; }
}

那么它只是一个更新你的过滤器代码的问题。过滤器不需要知道更多关于模型的信息,只需要知道它实现了IPasswordIConfirmPassword,它可以用强制转换来检查。

当然,为了使其正常工作,您必须在执行操作方法之前恢复原始值(或者在操作运行后进行日志记录),以便操作方法将具有正确的值。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var actionParam = filterContext.ActionParameters;
    IPassword password = null;
    IConfirmPassword confirmPassword = null;
    string originalPassword;
    string originalConfirmPassword;
    // Remove the password from the parameters
    if (actionParam.ContainsKey("model") && actionParam["model"] != null)
    {
        // If the model doesn't implement the interface, the result
        // here will be null.
        password = actionParam["model"] as IPassword;
        confirmPassword = actionParam["model"] as IConfirmPassword;
    }
    if (password != null)
    {
        // Store the original value so it can be restored later
        originalPassword = password.Password;
        password.Password = "Removed";
    }
    if (confirmPassword != null)
    {
        // Store the original value so it can be restored later
        originalConfirmPassword = confirmPassword.ConfirmPassword;
        confirmPassword.ConfirmPassword = "Removed";
    }
    string str = Json.Encode(filterContext.ActionParameters).Trim();
    string par = string.Empty;
    if (str.Length > 2)
    {
        par = str.Substring(1, str.Length - 2).Replace("'"", string.Empty);
    }
    ActionLog log = new ActionLog()
    {
        SessionId = filterContext.HttpContext.Session.SessionID,
        UserName = (request.IsAuthenticated) ? filterContext.HttpContext.User.Identity.Name : "Anonymous",
        Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
        Action = filterContext.ActionDescriptor.ActionName,
        ActionParameters = par,
        IsPost = request.HttpMethod.ToLower() == "post" ? true : false,
        IPAddress = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress,
        UserAgent = request.UserAgent,
        ActionDate = filterContext.HttpContext.Timestamp
    };
    //Store the Audit into the Database
    ActionLogContext context = new ActionLogContext();
    context.ActionLogs.Add(log);
    context.SaveChanges();
    // Restore the original values
    if (password != null)
    {
        password.Password = originalPassword;
    }
    if (confirmPassword != null)
    {
        confirmPassword.ConfirmPassword = originalConfirmPassword;
    }
    // Finishes executing the Action as normal
    base.OnActionExecuting(filterContext);
}