反序列化JSON并将对象保存到MySQL数据库

时间:2017-07-06 13:40:55

标签: c# mysql asp.net json

我正在尝试将POST请求中的对象保存到我的服务中。请求正在发送JSON:

{
"FirstName": "Ronnsie",
"LastName": "Wesleeyson",
"BirthPlace": "Zagreb",
"Gender": "M",
"OIB": "12345678901",
"CurrentPlace": "Mauritius",
"Department": "D_21510"
}

我得到的错误如下:

{
"Message": "An error has occurred.",
"ExceptionMessage": "Error executing the command 'INSERT INTO Employee (FirstName, LastName, BirthPlace, CurrentPlace, Gender, Department, OIB) VALUES (, , , Mauritius, 1, 21510, )'. The error is 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' , , Mauritius, 1, 21510, )' at line 1'." ...}

现在请求命中控制器:

    [HttpPost]
    [Route("")]
    public void Post([FromBody] Employee employee)
    {
        // saving id for the debugging purposes
        long id = persistence.SaveEmployee(employee);
    }

SaveEmployee 功能如下:

    public long SaveEmployee(Employee employee)
    {
        string sqlString = String.Format(
            "INSERT INTO Employee (FirstName, LastName, BirthPlace, CurrentPlace, Gender, Department, OIB) " + 
            "VALUES ({0}, {1}, {2}, {3}, {4}, {5}, {6})",
            employee.FirstName,
            employee.LastName,
            employee.BirthPlace,
            employee.CurrentPlace,
            employee.Gender == EmployeeGender.M ? 1 : 0,
            employee.Department.GetStringValue(),
            employee.OIB
        );

        MySqlCommand cmd = ExecuteSqlCommand(sqlString);
        return cmd.LastInsertedId;
    }

    MySqlCommand ExecuteSqlCommand(string sqlString)
    {
        try
        {
            // execute the SQL command
            MySqlCommand cmd = new MySqlCommand(sqlString, conn);
            cmd.ExecuteNonQuery();

            return cmd;
        }
        catch (MySqlException e)
        {
            // log the error
            throw new Exception(
                String.Format("Error executing the command '{0}'. The error is '{1}'.",
                             sqlString, e.Message));
        }
    }

我似乎无法在SQL语法中发现任何错误。但是,它可能是反序列化枚举的问题,因此它们是:

DepartmentCode.cs

[JsonConverter(typeof运算(StringEnumConverter))]     public enum DepartmentCode     {         D_21510,         D_21520,         D_21540,         D_21570,         D_SLFIN,         D_SLKPO     }

public static class DepartmentCodeExtensions
{
    const string S_21510 = "21510";
    const string S_21520 = "21520";
    const string S_21540 = "21540";
    const string S_21570 = "21570";
    const string S_SLFIN = "SLFIN";
    const string S_SLKPO = "SLKPO";

    public static string GetStringValue(this DepartmentCode dep)
    {
        switch (dep)
        {
            case DepartmentCode.D_21510:
                return S_21510;

            case DepartmentCode.D_21520:
                return S_21520;

            case DepartmentCode.D_21540:
                return S_21540;

            case DepartmentCode.D_21570:
                return S_21570;

            case DepartmentCode.D_SLFIN:
                return S_SLFIN;

            case DepartmentCode.D_SLKPO:
                return S_SLKPO;

            default:
                throw new ArgumentException("Given department code not supported.");
        }
    }

EmployeeGender.cs

[JsonConverter(typeof(StringEnumConverter))]
    public enum EmployeeGender
    {
        M,
        F
    }

关于错误是什么的任何想法?

2 个答案:

答案 0 :(得分:2)

您不应该使用public class LookupDao { private final Logger log = LogManager.getLogger(getClass()); @PersistenceContext private EntityManager entityManager; public LookupT findById(long id) throws Exception { log.info("Entered: LookupDao.findById(), id = " + id); // Pre-JPA (pre-conversion; note: commented out. No Hibernate Session conflicts) // ------- /* log.info("getting lookup id="+id); return sessionFactory.getCurrentSession().get(LookupT.class, id); */ // New JPA Approach (converted) // ---------------- CriteriaBuilder crbuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<LookupT> crquery = crbuilder.createQuery(LookupT.class); Root<LookupT> root = crquery.from(LookupT.class); crquery.where( (crbuilder.equal(root.get("id"), id)) ); Query q = entityManager.createQuery(crquery); return (LookupT)q.getSingleResult(); } 将参数放入SQL语句中。除了你看到的bug之外,它还让你对SQL注入有了很大的兴趣,就像@SLaks所提到的那样。

使用command parameters可以同时解决您的问题和SQL Injection漏洞。

答案 1 :(得分:2)

您有SQL注入漏洞。您应始终参数化SQL,这也是查询出现语法错误的原因,因为您没有将字符串参数放在引号内。这大致是你想要做的:

public long SaveEmployee(Employee employee)
    {
string connStr = "server=localhost;user=root;database=world;port=3306;password=******;";
MySqlConnection conn = new MySqlConnection(connStr);
        string sqlString = "INSERT INTO Employee (FirstName, LastName, BirthPlace, CurrentPlace, Gender, Department, OIB) " + 
            "VALUES (@FirstName,@LastName,@BirthPlace,@CurrentPlace,@Gender,@Department,@OIB)";

cmd.Parameters.AddWithValue(“@FirstName”, employee.FirstName);
cmd.Parameters.AddWithValue(“@LastName”, employee.LastName);
cmd.Parameters.AddWithValue(“@BirthPlace”, employee.BirthPlace);
cmd.Parameters.AddWithValue(“@CurrentPlace”, employee.CurrentPlace);
cmd.Parameters.AddWithValue(“@Gender”, employee.Gender == EmployeeGender.M ? 1 : 0);
cmd.Parameters.AddWithValue(“@Department”, employee.Department.GetStringValue());
cmd.Parameters.AddWithValue(“@OIB”, employee.OIB);

        MySqlCommand cmd = ExecuteSqlCommand(sqlString, conn);
        return cmd.LastInsertedId;
    }