繁体   English   中英

避免SQL注入java

[英]Avoiding SQL injection in java

我是 JavaEE 的新手,正在尝试通过检查数据库来学习制作一个简单的登录页面。 这是代码示例:

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

它应该容易受到 SQL 注入的攻击吧? 我将通过在 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);  

有没有办法像这样在 Java 中使用参数化查询? 任何人都可以使用参数化形式的查询来避免 SQL 注入吗?

是的,您可以使用PreparedStatement来做到这一点; 例如:

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();

这是 class 的简化版本,专门用于根据各种条件动态生成查询。 查询是使用 JPA CriteriaBuilder API 构建的。您需要根据您的表结构调整此代码。 一旦您理解了代码,您应该会发现这个 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];
         }
     }


}

可以使用消毒液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;*

当您尝试动态查询时,这将解决 Sql 注入问题。 它还将使我们免于强化扫描。

暂无
暂无

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

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