• ASP.NETCore MVC Model 数据注解过滤,post重复提交 ,XSS攻击


    本随笔只是个人学习记录。

    一、Model的数据注解

      开发asp.netcore 程序时(asp.netcore mvc 或这 asp.netcore webapi),在model 上使用数据注解,可以根据注解对客户端传递进来的数据进行过滤。具体为,当客户端数据传递到具体的action时,在进入action 方法体内部之前,对客户端传递进来的参数,根据数据注解进行验证,验证通过则执行action,不通过则返回。

    部分内置的数据注解特性如下(来源官网):

     更多特性,移步官网:https://docs.microsoft.com/zh-cn/dotnet/api/system.componentmodel.dataannotations?view=netcore-3.1

    数据注解参考官网:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-3.1

    https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/validation?view=aspnetcore-3.1&tabs=visual-studio

    https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-mvc-app/validation?view=aspnetcore-3.1

    二、POST重复提交

      在asp.netcore mvc中,提交数据到post 方法后,如果只是返回了某个view,而此时url并没有发生改变。再此刷新,会产生重复提交。为了防止重复提交,需要使用重定向。

    创建学生时,保存数据前,地址是 :https://localhost:5001/Home/Create

        

     保存数据后,地址还是:https://localhost:5001/Home/Create,此时,如果刷新网页,会造成 上一步骤的数据重复提交到 Create 进行保存。此时,会产生两条一样的数据保存到数据库,而这个过程,是不经意产生的,并不是我们想要的。

        

    如果使用重定向,则如下图所示,此时地址已经改变,数据不会发生post 重复提交,这里即是不会提交到Create

        

    三、XSS 跨站脚本攻击

      跨站脚本攻击,在html页面表单的input输入框中,输入脚本,比如html、js脚本,asp.netcore后台程序不经过处理则进行存储。取出数据显示时,会自动执行所保存的脚本,破坏应用程序。虽然前端可以对输入的数据进行编码,但终究不安全,需要在后台进行编码。

        

    四 此随笔关键代码片段:(源码太多,我只贴出关键代码片段)

    Model Student 代码:

    namespace MVCTemplate.Models
    {
        public class Student
        {
            public int Id { get; set; }
         
            //数据注解 data anotation
            [MinLength(3), Required,Display(Name ="FirstName")]
            public string FirstName { get; set; }
    
            [Required,Display(Name ="LastName")]
            public string LastName { get; set; }
    
            [Required,Display(Name ="性别")]
            public Gender Gender { get; set; }
    
            [Required,Display(Name ="生日")]
            public DateTime Birthday { get; set; }
    
        }
    
        public enum Gender
        {
            女=0,
            男=1,
            其他=2
        }
    }

    前端 HTML代码片段:

    @model MVCTemplate.Models.Student
    <h1>创建学生</h1>
    <div>
        <form method="post">
            <label asp-for="FirstName"></label>
            <input asp-for="@Model.FirstName" />
            <label asp-for="LastName"></label>
            <input asp-for="@Model.LastName" />
            <label asp-for="Birthday"></label>
            <input asp-for="@Model.Birthday" type="date" />
            <label asp-for="Gender"></label>
            <select asp-for="@Model.Gender" asp-        items="@Html.GetEnumSelectList<Gender>()"></select>
            <button type="submit">保存数据</button>
        </form>
    </div>

    后台 代码片段:

    public class HomeController : Controller
        {
            private readonly ILogger<HomeController> _logger;
    
            private readonly IRepository<Student> _repository;
    
            private readonly HtmlEncoder _htmlEncoder;
            /// <summary>
            /// 采用构造函数注入
            /// </summary>
            /// <param name="logger"></param>
            /// <param name="repository"></param>
            public HomeController(ILogger<HomeController> logger, IRepository<Student> repository, HtmlEncoder htmlEncoder)
            {
                _logger = logger;
                _repository = repository;
                _htmlEncoder = htmlEncoder;//htmlEoncoder,不需要再 ConfigureServices中手动注册,运行时会自动注册。
            }
    
            [HttpPost] //post 请求
            [ValidateAntiForgeryToken]//用于防止跨站请求伪造,针对post的Action,一定要加上这个。
            public IActionResult Create(Student stuModel)
            {
                //数据注解,mvc框架会在匹配参数时,根据数据注解来判断传递进来的参数是否合法(符合要求),如果不合法,
                //则不会进入到方法内。即数据注解会在参数匹配时进行拦截。
                if (!ModelState.IsValid)
                {
                    return Content("数据输入有误");
                }
    
                //对数据进行编码,防止XSS攻击。 比如会将输入的js脚本的<>这两个符号编码成&gt,&lt
                stuModel.FirstName = _htmlEncoder.Encode(stuModel.FirstName);
    
                //return new ObjectResult(stuModel);//返回json数据
                _repository.Add(stuModel);
    
                //带上 stuModel 返回页面detail。这种方式,容易产生重复提交post.因为返回后的地址不变,刷新页面,会重新提交post请求。
                //为了避免post重复提交,应该使用重定向
                // return View("Detail",stuModel);
                return RedirectToAction(nameof(Detail), stuModel);
            }
    
            public IActionResult Detail(Student stuModel)
            {
                return View(stuModel);
            }
            /*
             * 其他代码,太多了,这里就不贴出来了。
             */
        }
  • 相关阅读:
    选校总结
    位运算
    剑指
    机器学习之梯度下降法
    leetcode1348 Tweet Counts Per Frequency
    UVA10308 Roads in the North 树的最长路径
    负数的处理POJ1179Polygon
    Roadblocks
    Bus Stop
    蒜头君的城堡之旅(动态规划)
  • 原文地址:https://www.cnblogs.com/Fengyinyong/p/13741845.html
Copyright © 2020-2023  润新知