首页 新闻 会员 周边 捐助

Entity Framework中的ESQL查询有没有被注入式攻击的风险?

0
悬赏园豆:50 [已解决问题] 解决于 2014-10-30 16:51

EF中的查询可以使用ESQL语言,下面的代码接受一个字符串形式的查询条件:

public IQueryable<OpLog> GetOpLogBySql(string Sql)
{
    return this.ObjectContext.OpLog.Where(Sql);
}

其中的Sql参数可以是"it.date>'2014-1-1'"之类的字符串形式,是否有被注入的可能?

对EF的对象查询语言转T-SQL的过程不清楚,往高手赐教.

问题补充:

其实我想问的是能防止delete update insert这样的注入吗? 因为是在EF实体对象上的Where查找,会不会比传统的T-SQL更安全一些?

slmk的主页 slmk | 初学一级 | 园豆:9
提问于:2014-10-07 10:18
< >
分享
最佳答案
0

EF不是这样用的,你这样用跟回到SQL时间有什么区别了。

 

用EF最好就用EF的方式来写代码,where里面放的是条件表达式,用这种方式,就不会出现你说的问题了。

收获园豆:40
Alex_QY1987 | 小虾三级 |园豆:1888 | 2014-10-08 11:05

我也想那样写,可需要写一个通用的查询方式,因为用户的查询条件是五花八门的。总不能全部参数化?并且并不是每个参数都用到。

slmk | 园豆:9 (初学一级) | 2014-10-08 11:19

@slmk: 把能抽象的东西抽象出来

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.Data.Objects;
using System.Data;
using IDal;
using Model;
using Model.QueryModel;

namespace Dal
{
    public class DalBase<T> where T : class
    {
        private DbContext db = EFContextFactory.GetCurrentDbContext();
        public IDbSession _DbSession = DbSessionFactory.GetCurrenntDbSession();
        public T AddEntity(T entity)
        {
            db.Entry<T>(entity).State = EntityState.Added;
            //下面的写法统一
            db.SaveChanges();
            return entity;
        }
        //实现对数据库的修改功能
        public bool UpdateEntity(T entity)
        {
            db.Entry<T>(entity).State = EntityState.Modified;
            return db.SaveChanges() > 0;
        }

        //实现对数据库的删除功能
        public bool DeleteEntity(T entity)
        {
            //EF5.0的写法
            db.Set<T>().Attach(entity);
            db.Entry<T>(entity).State = EntityState.Deleted;
            return db.SaveChanges() > 0;
        }

        //实现对数据库的查询  --简单查询
        public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
        {
            //EF4.0的写法
            //return db.CreateObjectSet<T>().Where<T>(whereLambda).AsQueryable();
            //EF5.0的写法
            return db.Set<T>().Where<T>(whereLambda).AsQueryable();
        }

        /// <summary>
        /// 实现对数据的分页查询
        /// </summary>
        /// <typeparam name="S">按照某个类进行排序</typeparam>
        /// <param name="pageIndex">当前第几页</param>
        /// <param name="pageSize">一页显示多少条数据</param>
        /// <param name="total">总条数</param>
        /// <param name="whereLambda">取得排序的条件</param>
        /// <param name="isAsc">如何排序,根据倒叙还是升序</param>
        /// <param name="orderByLambda">根据那个字段进行排序</param>
        /// <returns></returns>
        public IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Expression<Func<T, bool>> whereLambda,
                                                 bool isAsc, Expression<Func<T, S>> orderByLambda)
        {
            //EF4.0和上面的查询一样
            //EF5.0
            var temp = db.Set<T>().Where<T>(whereLambda);
            total = temp.Count(); //得到总的条数
            //排序,获取当前页的数据
            if (isAsc)
            {
                temp = temp.OrderBy<T, S>(orderByLambda)
                    .Skip<T>(pageSize * (pageIndex - 1)) //越过多少条
                    .Take<T>(pageSize).AsQueryable(); //取出多少条
            }
            else
            {
                temp = temp.OrderByDescending<T, S>(orderByLambda)
                    .Skip<T>(pageSize * (pageIndex - 1)) //越过多少条
                    .Take<T>(pageSize).AsQueryable(); //取出多少条
            }
            return temp.AsQueryable();
        }
        public Expression<Func<T, To>> GetSortExpression<T, To>(String sortBy)
        {
            var param = Expression.Parameter(typeof(T), "x");
            Expression expr = Expression.Property(param, sortBy);
            return Expression.Lambda<Func<T, To>>(expr, param);
        }

        public IQueryable<T> SortList(IQueryable<T> q, QueryBase pq)
        {
            var propertyType = typeof(T).GetProperty(pq.SortField).PropertyType;
            var sortField = pq.SortField;
            if (pq.Direction.ToUpper() == "ASC")
            {
                if (propertyType == typeof(bool))
                {

                    q = q.OrderBy(GetSortExpression<T, bool>(sortField));
                }
                else if (propertyType == typeof(int))
                {
                    q = q.OrderBy(GetSortExpression<T, int>(sortField));
                }
                else if (propertyType == typeof(int?))
                {
                    q = q.OrderBy(GetSortExpression<T, int?>(sortField));
                }
                else if (propertyType == typeof(DateTime))
                {
                    q = q.OrderBy(GetSortExpression<T, DateTime>(sortField));
                }

                else if (propertyType == typeof(DateTime?))
                {
                    q = q.OrderBy(GetSortExpression<T, DateTime?>(sortField));
                }
                else
                {
                    q = q.OrderBy(GetSortExpression<T, object>(sortField));
                }
            }
            else
            {
                if (propertyType == typeof(bool))
                {
                    q = q.OrderByDescending(GetSortExpression<T, bool>(sortField));
                }
                else if (propertyType == typeof(int))
                {
                    q = q.OrderByDescending(GetSortExpression<T, int>(sortField));
                }
                else if (propertyType == typeof(int?))
                {
                    q = q.OrderByDescending(GetSortExpression<T, int?>(sortField));
                }
                else if (propertyType == typeof(DateTime))
                {
                    q = q.OrderByDescending(GetSortExpression<T, DateTime>(sortField));
                }
                else if (propertyType == typeof(DateTime?))
                {
                    q = q.OrderByDescending(GetSortExpression<T, DateTime?>(sortField));
                }
                else
                {
                    q = q.OrderByDescending(GetSortExpression<T, object>(sortField));
                }
            }
            return q;
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model.QueryModel
{
    public class QueryBase
    {
        public int PageIndex { get; set; }

        public int PageSize { get; set; }

        public int Total { get; set; }

        public string SortField { get; set; }
        public string Direction { get; set; }
    }
}


上面是两个基类

下面是两个具体类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IDal;
using Model;
using Model.QueryModel;

namespace Dal
{
    public partial class DalT_Articles : DalBase<T_Articles>, IT_Articles
    {
        public IQueryable<T_Articles> LoadSearchData(ArticleQuery query)
        {
            var temp = _DbSession.DalT_Articles.LoadEntities(u => true);
            if (!string.IsNullOrEmpty(query.Keys))
            {
                temp = temp.Where<T_Articles>(c => c.Title1.Contains(query.Keys));
            }
            if (!string.IsNullOrEmpty(query.SugI))
            {
                var i = int.Parse(query.SugI);
                temp = temp.Where<T_Articles>(c => c.SugI == i);
            }
            if (!string.IsNullOrEmpty(query.Sug))
            {
                var i = int.Parse(query.Sug);
                temp = temp.Where<T_Articles>(c => c.Sug == i);
            }
            query.Total = temp.Count();
            temp = SortList(temp, query);//实现排序
            return temp.Skip(query.PageSize * (query.PageIndex - 1)).Take(query.PageSize);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model.QueryModel
{
    public class ArticleQuery : QueryBase
    {
        public string Keys { get; set; }
        public string SugI { get; set; }//首页推荐
        public string Sug { get; set; }//推荐显示
    }
}

你研究一下吧。

面向对象,封装、继续、多态啊!

 

Alex_QY1987 | 园豆:1888 (小虾三级) | 2014-10-08 11:29

@Alex_QY1987: 谢谢回复!Expression<Func<T, bool>>是一个不错的思路。这种表达式对象如何传递到后台呢?

slmk | 园豆:9 (初学一级) | 2014-10-08 14:18
其他回答(4)
0

可以传字符串的形式的查询条件,并不意味着你要让用户直接写"it.date>'2014-1-1'",这个字符串应该是你拼出来的,

你不检查SQL注入,那是你的问题,别怪到EF身上哦。

爱编程的大叔 | 园豆:30844 (高人七级) | 2014-10-07 10:23

也就是说,ESQL有被注入的风险了?

支持(0) 反对(0) slmk | 园豆:9 (初学一级) | 2014-10-07 12:57

@slmk: 当然。任何编程语言都无法和人对抗,尤其是程序员。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2014-10-07 13:22
0

用参数化查询

Magic.Z | 园豆:232 (菜鸟二级) | 2014-10-07 14:10
0

风险是有的,建议使用参数化查询。

收获园豆:5
晓菜鸟 | 园豆:2594 (老鸟四级) | 2014-10-07 16:30
0

没有利用参数化查询,又是动态构造的sql语句,都有被注入的风险。需要靠我们(开发者)来保证的。

收获园豆:5
幻天芒 | 园豆:37205 (高人七级) | 2014-10-08 08:39

其实我想问的是能防止delete update insert这样的注入吗? 因为是在EF实体对象上的Where查找,会不会比传统的T-SQL更安全一些?

支持(0) 反对(0) slmk | 园豆:9 (初学一级) | 2014-10-08 09:19

@slmk: 我只问你一个问题,如果你确实想要Delete的时候,EF怎么办?

你让EF如何分辨是你干的还是你干的或者是你干的好事?

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2014-10-08 09:35

@爱编程的大叔: 哥们,你看题目了吗?做过测试吗?在上面的Where里面给我注入一个delete我看看?

支持(0) 反对(0) slmk | 园豆:9 (初学一级) | 2014-10-08 09:46

@slmk: 好象你对这个比较有兴趣,我就奇怪的是测试一下对你就这么难么?

园友最多只能从技术层面或是你没注意的角度帮你分析问题,如果一个简单的测试就能得出的答案,

你还来问别人测试过没有,这个似乎过了。

不同园友的答案你也看到了,都是建议参数化查询之类的。

其实就算不是参数化查询,也有简单的方法先过滤一下SQL的,保证不出现SQL注入的情况。

对于LINQ强类型编程模式,我基本可以保证95%以上的情况的不需要使用动态构造的SQL,

另外5%小心点,写个函数专门处理下不就得了。

安全问题不要交给别人。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2014-10-08 09:55

@爱编程的大叔: 你就不敢兴趣吗?如果没有风险,干嘛费事去过滤SQL呢?我觉得这个问题大家都会遇到,所以才问的。希望有时间和已经测试过的园友可以解答一下!

支持(0) 反对(0) slmk | 园豆:9 (初学一级) | 2014-10-08 10:04

@slmk: 建议用SQL SERVER Profiler监视下sql语句。

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2014-10-08 10:24

@爱编程的大叔: 大叔还是这么直白,假期结束了,总感觉缺点什么...

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2014-10-08 10:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册