[英]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.