我试图从我的动作过滤器中删除参数中捕获的密码,并将其替换为“已删除”一词,以便将参数存储在数据库中进行记录。密码存储在ViewModel
中(取决于操作)。以下是关于我想要实现的“伪代码”。
如何屏蔽/替换要保存在数据库中的密码?我遇到的主要问题是我不知道如何访问密码参数并进行更改。我尝试使用actionParams.TryGetValue("model, out value)
来获取它,但问题是我不知道值的类型,它会根据操作而改变。此外,我无法在actionParams["model"]
上调用许多方法(例如包含)
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)
答案 0 :(得分:1)
一种方法是使用接口作为抽象,因此您不直接处理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);
}