替换动作过滤器中的参数
本文关键字:参数 过滤器 替换 | 更新日期: 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; }
}
那么它只是一个更新你的过滤器代码的问题。过滤器不需要知道更多关于模型的信息,只需要知道它实现了IPassword
或IConfirmPassword
,它可以用强制转换来检查。
当然,为了使其正常工作,您必须在执行操作方法之前恢复原始值(或者在操作运行后进行日志记录),以便操作方法将具有正确的值。
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);
}