详解ASP.NET MVC Form表单验证

2019-05-22 20:58:31于丽

  2. 如果验证通过,程序会进行验证AuthorizeAttribute的Roles和User属性。

  3. 如果验证通过,程序会验证配置文件中对应的Roles和Users属性。

  验证配置文件的方法如下:

  private bool ValidateAuthorizeConfig(Principal principal, AuthorizationContext context)
  {
    //action可能有重载,重载时应该标记ActionName区分
    ActionNameAttribute actionNameAttr = context.ActionDescriptor
      .GetCustomAttributes(typeof(ActionNameAttribute), false)
      .OfType<ActionNameAttribute>().FirstOrDefault();
    string actionName = actionNameAttr == null ? null : actionNameAttr.Name;
    AuthorizationConfig ac = ParseAuthorizeConfig(actionName, context.RouteData);
    if (ac != null)
    {
      if (!principal.IsInRole(ac.Roles))
      {
        return false;
      }
      if (!principal.IsInUser(ac.Users))
      {
        return false;
      }
    }
    return true;
  }
 
  private AuthorizationConfig ParseAuthorizeConfig(string actionName, RouteData routeData)
  {
    string areaName = routeData.DataTokens["area"] as string;
    string controllerName = null;
    object controller, action;
    if(string.IsNullOrEmpty(actionName))
    {
      if(routeData.Values.TryGetValue("action", out action))
      {
        actionName = action.ToString();
      }
    }
    if (routeData.Values.TryGetValue("controller", out controller))
    {
      controllerName = controller.ToString();
    }
    if(!string.IsNullOrEmpty(controllerName) && !string.IsNullOrEmpty(actionName))
    {
      return AuthorizationConfig.ParseAuthorizationConfig(
        areaName, controllerName, actionName);
    }
    return null;
  }
}

  可以看到,它会根据当前请求的area、controller和action名称,通过一个AuthorizationConfig类进行验证,该类的定义如下:

public class AuthorizationConfig
{
  public string Roles { get; set; }
  public string Users { get; set; }
 
  private static XDocument _doc;
 
  //配置文件路径
  private static string _path = "~/Identity/Authorization.xml";
 
  //首次使用加载配置文件
  static AuthorizationConfig()
  {
    string absPath = HttpContext.Current.Server.MapPath(_path);
    if (File.Exists(absPath))
    {
      _doc = XDocument.Load(absPath);
    }
  }
 
  //解析配置文件,获得包含Roles和Users的信息
  public static AuthorizationConfig ParseAuthorizationConfig(string areaName, string controllerName, string actionName)
  {
    EnsureHelper.EnsureNotNullOrEmpty(controllerName, "controllerName");
    EnsureHelper.EnsureNotNullOrEmpty(actionName, "actionName");
 
    if (_doc == null)
    {
      return null;
    }
    XElement rootElement = _doc.Element("root");
    if (rootElement == null)
    {
      return null;
    }
    AuthorizationConfig info = new AuthorizationConfig();
    XElement rolesElement = null;
    XElement usersElement = null;
    XElement areaElement = rootElement.Elements("area")
      .Where(e => CompareName(e, areaName)).FirstOrDefault();
    XElement targetElement = areaElement ?? rootElement;
    XElement controllerElement = targetElement.Elements("controller")
      .Where(e => CompareName(e, controllerName)).FirstOrDefault();
 
    //如果没有area节点和controller节点则返回null
    if (areaElement == null && controllerElement == null)
    {
      return null;
    }
    //此时获取标记的area
    if (controllerElement == null)
    {
      rootElement = areaElement.Element("roles");
      usersElement = areaElement.Element("users");
    }
    else
    {
      XElement actionElement = controllerElement.Elements("action")
        .Where(e => CompareName(e, actionName)).FirstOrDefault();
      if (actionElement != null)
      {
        //此时获取标记action的
        rolesElement = actionElement.Element("roles");
        usersElement = actionElement.Element("users");
      }
      else
      {
        //此时获取标记controller的
        rolesElement = controllerElement.Element("roles");
        usersElement = controllerElement.Element("users");
      }
    }
    info.Roles = rolesElement == null ? null : rolesElement.Value;
    info.Users = usersElement == null ? null : usersElement.Value;
    return info;
  }
 
  private static bool CompareName(XElement e, string value)
  {
    XAttribute attribute = e.Attribute("name");
    if (attribute == null || string.IsNullOrEmpty(attribute.Value))
    {
      return false;
    }
    return attribute.Value.Equals(value, StringComparison.OrdinalIgnoreCase);
  }
}