简体   繁体   English

避免SQL注入java

[英]Avoiding SQL injection in java

I am new to JavaEE and trying to learn to make a simple login page by checking the database.我是 JavaEE 的新手,正在尝试通过检查数据库来学习制作一个简单的登录页面。 Here is the code sample:这是代码示例:

ResultSet result=null;
Statement s = (Statement) con.createStatement();
result=s.executeQuery("select username from Table where ID="+id and " password="+password);

It should be vulnerable to SQL injection right?它应该容易受到 SQL 注入的攻击吧? I would do this by using parametrized query in ASP.NET like the following:我将通过在 ASP.NET 中使用参数化查询来执行此操作,如下所示:

SqlConnection con = new SqlConnection();
SqlCommand cmd=new SqlCommand("select username from Table where ID=@id and password=@password",con);    
cmd.Parameters.AddWithValue("@id", id); 
cmd.Parameters.AddWithValue("@password", password);  

Is there any way to use parametrized queries in Java like this?有没有办法像这样在 Java 中使用参数化查询? Can anyone use that query in parametrized form to avoid SQL injection?任何人都可以使用参数化形式的查询来避免 SQL 注入吗?

Yes you can do this with PreparedStatement ;是的,您可以使用PreparedStatement来做到这一点; for example:例如:

PreparedStatement preparedStatement = con.PreparedStatement(
        "SELECT * FROM MY_TABLE WHERE condition1 = ? AND condition2 = ?");
preparedStatement.setString(1,condition1_value);
preparedStatement.setString(2,condition2_value);
ResultSet rs = preparedStatement.executeQuery();

Here's a abridged version of a class dedicated to dynamically producing a query based on various criteria.这是 class 的简化版本,专门用于根据各种条件动态生成查询。 The Query is constructed using JPA CriteriaBuilder API. You will need to adapt this code to your table structure.查询是使用 JPA CriteriaBuilder API 构建的。您需要根据您的表结构调整此代码。 You should find this class easy to extend once you a understand the code.一旦您理解了代码,您应该会发现这个 class 很容易扩展。

@Stateless
public class sample {


    @PersistenceContext
    private EntityManager em;
    private CriteriaBuilder criteriaBuilder;
    private Root<Branch> root;
    private CriteriaQuery<Integer> query;


    @PostConstruct
    private void init(){
        criteriaBuilder = em.getCriteriaBuilder();
        resetCriteria();
        query = criteriaBuilder.createQuery(Integer.class);
        root = query.from(Branch.class);
    }


    private String branchName;
    private Predicate[] validPredicates;


    public void resetCriteria() {
        branchName = "";
        query = criteriaBuilder.createQuery(Integer.class);
        validPredicates = new Predicate[0];
    }




    public void setBranchName(String criteria){
        this.branchName = criteria;
    }




    public List<Integer> runQuery(){
        buildPredicates();

        if(validPredicates.length != 0){
            query.select(root.<Integer>get("branchID"))
                .where(criteriaBuilder.and(validPredicates));
        }
        else{
            query.select(root.<Integer>get("branchID"));
        }
        TypedQuery<Integer> q = em.createQuery(query);
        List<Integer> result = q.getResultList();
        return result;
    }




    private void buildPredicates(){
         ArrayList<Predicate> predicates = new ArrayList<Predicate>();

         if(branchName != null && !branchName.isEmpty()){
             StringBuilder sb =  new StringBuilder();
             sb.append("%")
                .append(branchName)
                .append("%");
            Predicate p = criteriaBuilder.like(root.<String>get("branchName"), sb.toString());
            predicates.add(p);
         }

         createPredicateArray(predicates);
     }  
     private void createPredicateArray(List<Predicate> predicates){
         if (predicates.size() > 0){
            validPredicates = new Predicate[predicates.size()];
            predicates.toArray(validPredicates);
         }
         else{
            validPredicates = new Predicate[0];
         }
     }


}

You can use the sanitizer class;可以使用消毒液class;

*jdbcTemplate.execute(sanitizer.sanitize(sql), (PreparedStatementCallback<Integer>) preparedStatement -> {
preparedStatement.execute();* 
Sanitizer class:
*import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.springframework.data.domain.Sort.Direction;
public class Sanitizer {

     // Used to sanitize a path for fortify
    public String sanitize(String path) throws IllegalArgumentException {
        if (path == null) {
            return null;
        }
        String cleanString = "";
        for (int i = 0; i < path.length(); ++i) {
            cleanString += sanitizeChar(path.charAt(i));
        }
        return cleanString;
    }
    public byte[] sanitize(byte[] bytes) throws IOException, Exception, DecoderException {
        if (bytes == null) {
            return null;
        }
        String hex = Hex.encodeHexString(bytes);
        return Hex.decodeHex(sanitize(hex));
    }
    public Long sanitize(Long input) throws IllegalArgumentException {
        if (input == null) {
            return null;
        }
        if (input instanceof Long) {
            return input;
        } else {
            throw new IllegalArgumentException("Invalid input!");
        }
    }
    public Integer sanitize(Integer input) throws IllegalArgumentException {
        if (input == null) {
            return null;
        }
        if (input instanceof Integer) {
            return input;
        } else {
            throw new IllegalArgumentException("Invalid input!");
        }
    }
    public List<String> sanitize(List<String> inputList) throws IllegalArgumentException {
        List<String> list = new ArrayList<>();
        if (isNullOrEmpty(inputList)) {
            return list;
        }
        for (String input : inputList) {
            list.add(sanitize(input));
        }
        return list;
    }
    public Direction sanitize(Direction direction) {
        if (direction == null) {
            return null;
        }
        String sanitizedStr = direction.toString();
        return Direction.valueOf(sanitize(sanitizedStr));
    }

    private char sanitizeChar(char character) throws IllegalArgumentException {

        for (int i = 0; i < 128; ++i) {
            if (character == i) {
                return (char) i;
            }
        }
        switch (character) {
        case '.':
            return '.';
        case '_':
            return '_';
        case '-':
            return '-';
        case '?':
            return '?';
        case '/':
            return '/';
        case '=':
            return '=';
        case ':':
            return ':';
        case '\\':
            return '\\';
        case '@':
            return '@';
        case '&':
            return '&';
        case '%':
            return '%';
        case '+':
            return '+';
        case ',':
            return ',';
        case '#':
            return '#';
        case '(':
            return '(';
        case ')':
            return ')';
        case '{':
            return '{';
        case '}':
            return '}';
        case '$':
            return '$';
        case '*':
            return '*';
        case '<':
            return '<';
        case '>':
            return '>';
        case '!':
            return '!';
        case ' ':
            return ' ';
        case '~':
            return '~';
        case '^':
            return '^';
        case '`':
            return '`';
        case ';':
            return ';';
        case '[':
            return '[';
        case ']':
            return ']';
        case '|':
            return '|';
        case '"':
            return '"';
        case '\'':
            return '\'';
        case '  ':
            return '    ';
        }
        throw new IllegalArgumentException("Invalid character found:" + character + ":");
    }
        public static <T> boolean isNullOrEmpty(Collection<T> list) {
    if (list == null || list.size() == 0) {
        return true;
    }
    return false;*

This will solve the Sql injection when you are trying to get dynamic query on the fly.当您尝试动态查询时,这将解决 Sql 注入问题。 It will also save us from fortify scans.它还将使我们免于强化扫描。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM