백엔드 개발 PHP 튜토리얼 ThinkPHP 프레임워크 보안 구현 분석_php 예

ThinkPHP 프레임워크 보안 구현 분석_php 예

May 16, 2016 pm 07:57 PM
thinkphp 프레임워크 안전

ThinkPHP 프레임워크는 중국에서 가장 인기 있는 PHP 프레임워크 중 하나입니다. 외국 프레임워크와 비교할 수는 없지만 중국어 매뉴얼이 매우 포괄적이라는 장점이 있습니다. 최근 SQL 인젝션에 대해 공부하고 있는데, 이전에 TP 프레임워크를 사용할 때는 기본 레이어에서 보안 기능을 제공했기 때문에 개발 과정에서 보안 문제를 크게 고려하지 않았습니다.

1. I 함수를 말해야 합니다

TP 시스템은 입력 변수 필터링을 위한 I 함수를 제공합니다. 전체 함수 본문의 의미는 I('get.'), I('post.id') 등 다양한 형식의 데이터를 얻은 다음 (기본적으로) htmlspecialchars 함수를 사용하여 이를 처리하는 것입니다.

보안 필터링을 위해 다른 방법을 사용해야 하는 경우 /ThinkPHP/Conf/convention.php에서 설정할 수 있습니다.

'DEFAULT_FILTER'    => 'strip_tags',
//也可以设置多种过滤方法
'DEFAULT_FILTER'    => 'strip_tags,stripslashes',
로그인 후 복사

/ThinkPHP/Common/functions.php에서 I 함수를 찾을 수 있으며 소스 코드는 다음과 같습니다.

/**
 * 获取输入参数 支持过滤和默认值
 * 使用方法:
 * <code>
 * I('id',0); 获取id参数 自动判断get或者post
 * I('post.name','','htmlspecialchars'); 获取$_POST['name']
 * I('get.'); 获取$_GET
 * </code>
 * @param string $name 变量的名称 支持指定类型
 * @param mixed $default 不存在的时候默认值
 * @param mixed $filter 参数过滤方法
 * @param mixed $datas 要获取的额外数据源
 * @return mixed
 */
function I($name,$default='',$filter=null,$datas=null) {
  static $_PUT  =  null;
  if(strpos($name,'/')){ // 指定修饰符
    list($name,$type)   =  explode('/',$name,2);
  }elseif(C('VAR_AUTO_STRING')){ // 默认强制转换为字符串
    $type  =  's';
  }
  /*根据$name的格式获取数据:先判断参数的来源,然后再根据各种格式获取数据*/
  if(strpos($name,'.')) {list($method,$name) =  explode('.',$name,2);} // 指定参数来源
  else{$method =  'param';}//设定为自动获取
  switch(strtolower($method)) {
    case 'get'   :  $input =& $_GET;break;
    case 'post'  :  $input =& $_POST;break;
    case 'put'   :  /*此处省略*/
    case 'param'  :  /*此处省略*/
    case 'path'  :  /*此处省略*/
  }
  /*对获取的数据进行过滤*/
  if('' // 获取全部变量
    $data    =  $input;
    $filters  =  isset($filter)&#63;$filter:C('DEFAULT_FILTER');
    if($filters) {
      if(is_string($filters)){$filters  =  explode(',',$filters);} //为多种过滤方法提供支持
      foreach($filters as $filter){
        $data  =  array_map_recursive($filter,$data); //循环过滤
      }
    }
  }elseif(isset($input[$name])) { // 取值操作
    $data    =  $input[$name];
    $filters  =  isset($filter)&#63;$filter:C('DEFAULT_FILTER');
    if($filters) {   /*对参数进行过滤,支持正则表达式验证*/
      /*此处省略*/
    }
    if(!empty($type)){ //如果设定了强制转换类型
      switch(strtolower($type)){
        case 'a': $data = (array)$data;break;  // 数组 
        case 'd': $data = (int)$data;break;  // 数字 
        case 'f': $data = (float)$data;break;  // 浮点  
        case 'b': $data = (boolean)$data;break;  // 布尔
        case 's':  // 字符串
        default:$data  =  (string)$data;
      }
    }
  }else{ // 变量默认值
    $data    =  isset($default)&#63;$default:null;
  }
  is_array($data) && array_walk_recursive($data,'think_filter'); //如果$data是数组,那么用think_filter对数组过滤
  return $data;
}
로그인 후 복사

음, 기능은 기본적으로 세 부분으로 나누어져 있습니다.
첫 번째 블록은 다양한 형식의 데이터를 얻는 것입니다.
두 번째 블록은 2차원 배열이든 3차원 배열이든 획득한 데이터에 대해 루프 인코딩을 수행합니다.
끝에서 두 번째 줄인 세 번째 블록은 think_filter를 호출하여 데이터에 대한 신비한 처리의 마지막 단계를 수행합니다.

먼저 think_filter 함수를 추적해 보겠습니다.

//1536行 版本3.2.3最新添加
function think_filter(&$value){// 过滤查询特殊字符  
  if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){    
    $value .= ' ';  
  }
}
로그인 후 복사

이 기능은 매우 간단하며 특정 키워드 뒤에 공백을 추가하여 한눈에 볼 수 있습니다.

근데 think_filter라는 함수는 공백만 추가하는 기능인데 어떤 필터링 효과가 있나요?

사용자가 로그인했는지, 특정 상품을 구매할 수 있는지 등 중요한 논리적 확인은 서버 측에서 확인해야 한다는 사실은 모두가 알고 있습니다. 쉽게 우회할 수 있습니다. 같은 이유로 프로그램에서 in/exp와 같은 논리 구조는 서버에 의해 가장 잘 제어됩니다.

서버에 전달된 데이터가 id[0]=in&id[1]=1,2,3일 때 think_filter 함수가 없으면 다음 표에서 1로 파싱되어, 서버 측 논리 구문 분석으로 간주됩니다. 하지만 아래 표 2와 같이 되면 여분의 공간이 생기기 때문에 매칭과 파싱이 불가능해 허점을 피할 수 있다.

$data['id']=array('in'=>'1,2,3') 
//经过think_filter过滤之后,会变成介个样子:
$data['id']=array('in '=>'1,2,3')
로그인 후 복사

2. SQL 인젝션

관련 파일은 다음과 같습니다:/ThinkPHP/Library/Think/Db.class.php (3.2.3에서 /ThinkPHP/Library/Think/Db/Driver.class.php로 변경됨) 및 /ThinkPHP/Library/Think / Model.class.php. Model.class.php 파일은 curd가 직접 호출하는 함수와 외부 인터페이스를 직접 제공합니다. Driver.class.php의 함수는 curd 연산에 의해 간접적으로 호출됩니다.

//此次主要分析如下语句:
M('user')->where($map)->find();  //在user表根据$map的条件检索出一条数据

로그인 후 복사

TP의 처리 아이디어에 대해 간단히 이야기해 보세요.

먼저 Model 클래스를 사용자 개체로 인스턴스화한 다음 사용자 개체에서 where 함수를 호출하여 $map을 처리합니다. 즉, $map에서 일부 형식 지정을 수행하고 이를 사용자 개체의 멤버 변수 $options에 할당합니다. (다른 일관적인 연산을 위한 경우에는 SQL 문을 직접 스플라이싱하는 것이 아니라 먼저 사용자 개체의 해당 멤버 변수에 값을 할당합니다. 따라서 일관적인 연산을 작성할 때 스플라이싱과 같은 키워드의 순서를 고려할 필요가 없습니다. SQL 문), 찾기 함수를 호출합니다.

찾기 함수는 기본 함수를 호출합니다. 데이터를 얻으려면 드라이버 클래스에서 선택하세요. 선택 기능에 관해서는 또 다른 이야기입니다.

select는 curd 작업 외에도 pdo 바인딩도 처리하므로 여기서는 curd 작업만 고려하므로 select에서 buildSelectSql을 호출하여 페이징 정보를 처리하고,parSQL을 호출하여 설정된 순서대로 SQL 문을 조합합니다.

SQL 문을 연결하는데 필요한 모든 매개변수를 멤버 변수에 넣었음에도 불구하고 형식은 일률적이지 않습니다. 문자열 형식일 수도 있고, 배열 형식일 수도 있고, TP에서 제공하는 특수 쿼리 형식일 수도 있습니다. , 예: $data['id']=array('gt','100'); 따라서 접합하기 전에 통일된 형식화를 위해 해당 처리 함수를 호출해야 합니다. 분석을 위해 복잡한 예제인parseWhere를 선택했습니다.

보안과 관련하여 I 함수를 사용하여 데이터를 얻으면 기본적으로 htmlspecialchars 처리가 수행되므로 XSS 공격에 효과적으로 저항할 수 있지만 SQL 주입에는 거의 영향을 미치지 않습니다.

SQL 주입과 관련된 기호를 필터링할 때 TP의 접근 방식은 매우 영리합니다. 먼저 일반 논리에 따라 사용자의 입력을 처리한 다음 최종 SQL 문에 가장 가까운parseWhere,parseHaving과 같은 함수에서 안전한 처리를 수행합니다. 이 순서는 처리 중에 주입을 방지합니다.

물론 가장 일반적인 처리 방법은 addlashes 입니다. 이전의 Waves on the beach에 따르면 필터링에는 mysql_real_escape_string을 사용하는 것이 좋지만 이 기능은 데이터베이스가 연결된 경우에만 사용할 수 있습니다.

이 분야에서는 TP가 어느 정도 최적화를 할 수 있을 것 같습니다. 결국 이 지점에 도달한 모든 사람은 데이터베이스에 연결됩니다.

다음으로 분석이 시작됩니다.

Model 개체의 몇 가지 멤버 변수에 대해 이야기해 보겠습니다.

// 主键名称
protected $pk   = 'id';
// 字段信息
protected $fields = array();
// 数据信息
protected $data  = array();
// 查询表达式参数
protected $options = array();
// 链操作方法列表
protected $methods = array('strict','order','alias','having','group','lock','distinct','auto','filter','validate','result','token','index','force')
接下来分析where函数:
public function where($where,$parse=null){
  //如果非数组格式,即where('id=%d&name=%s',array($id,$name)),对传递到字符串中的数组调用mysql里的escapeString进行处理
  if(!is_null($parse) && is_string($where)) { 
    if(!is_array($parse)){ $parse = func_get_args();array_shift($parse);}
    $parse = array_map(array($this->db,'escapeString'),$parse);
    $where = vsprintf($where,$parse); //vsprintf() 函数把格式化字符串写入变量中
  }elseif(is_object($where)){
    $where =  get_object_vars($where);
  }
  if(is_string($where) && '' != $where){
    $map  =  array();
    $map['_string']  =  $where;
    $where =  $map;
  }   
  //将$where赋值给$this->where
  if(isset($this->options['where'])){     
    $this->options['where'] =  array_merge($this->options['where'],$where);
  }else{
    $this->options['where'] =  $where;
  }
   
  return $this;
}
로그인 후 복사

where函数的逻辑很简单,如果是where('id=%d&name=%s',array($id,$name))这种格式,那就对$id,$name变量调用mysql里的escapeString进行处理。escapeString的实质是调用mysql_real_escape_string、addslashes等函数进行处理。

最后将分析之后的数组赋值到Model对象的成员函数——$where中供下一步处理。

再分析find函数:

//model.class.php  行721  版本3.2.3
public function find($options=array()) {
  if(is_numeric($options) || is_string($options)){ /*如果传递过来的数据是字符串,不是数组*/
    $where[$this->getPk()] =  $options;
    $options        =  array();
    $options['where']    =  $where; /*提取出查询条件,并赋值*/
  }
  // 根据主键查找记录
  $pk = $this->getPk();
  if (is_array($options) && (count($options) > 0) && is_array($pk)) {
    /*构造复合主键查询条件,此处省略*/
  }
  $options['limit']  =  1;                 // 总是查找一条记录
  $options      =  $this->_parseOptions($options);   // 分析表达式
  if(isset($options['cache'])){
    /*缓存查询,此处省略*/
  }
  $resultSet = $this->db->select($options);
  if(false === $resultSet){  return false;}
  if(empty($resultSet)) {  return null; }      // 查询结果为空    
  if(is_string($resultSet)){  return $resultSet;}  //查询结果为字符串
  // 读取数据后的处理,此处省略简写
  $this->data = $this->_read_data($resultSet[0]);
  return $this->data;
}

로그인 후 복사

$Pk为主键,$options为表达式参数,本函数的作用就是完善成员变量——options数组,然后调用db层的select函数查询数据,处理后返回数据。

跟进_parseOptions函数:

protected function _parseOptions($options=array()) { //分析表达式
  if(is_array($options)){
    $options = array_merge($this->options,$options);
  }
  /*获取表名,此处省略*/
  /*添加数据表别名,此处省略*/
  $options['model']    =  $this->name;// 记录操作的模型名称
  /*对数组查询条件进行字段类型检查,如果在合理范围内,就进行过滤处理;否则抛出异常或者删除掉对应字段*/
  if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])){
    foreach ($options['where'] as $key=>$val){
      $key = trim($key);
      if(in_array($key,$fields,true)){  //如果$key在数据库字段内,过滤以及强制类型转换之
        if(is_scalar($val)) { 
        /*is_scalar 检测是否为标量。标量是指integer、float、string、boolean的变量,array则不是标量。*/     
          $this->_parseType($options['where'],$key);
        }
      }elseif(!is_numeric($key) && '_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){
        // 如果$key不是数字且第一个字符不是_,不存在.(|&等特殊字符
        if(!empty($this->options['strict'])){  //如果是strict模式,抛出异常
          E(L('_ERROR_QUERY_EXPRESS_').':['.$key.'=>'.$val.']');
        }  
        unset($options['where'][$key]); //unset掉对应的值
      }
    }
  } 
  $this->options =  array();      // 查询过后清空sql表达式组装 避免影响下次查询
  $this->_options_filter($options);    // 表达式过滤
  return $options;
}

로그인 후 복사

本函数的结构大概是,先获取了表名,模型名,再对数据进行处理:如果该条数据不在数据库字段内,则做出异常处理或者删除掉该条数据。否则,进行_parseType处理。parseType此处不再跟进,功能为:数据类型检测,强制类型转换包括int,float,bool型的三种数据。

函数运行到此处,就该把处理好的数据传到db层的select函数里了。此时的查询条件$options中的int,float,bool类型的数据都已经进行了强制类型转换,where()函数中的字符串(非数组格式的查询)也进行了addslashes等处理。

继续追踪到select函数,就到了driver对象中了,还是先列举几个有用的成员变量:

// 数据库表达式
protected $exp = array('eq'=>'=','neq'=>'<>','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE','in'=>'IN','notin'=>'NOT IN','not in'=>'NOT IN','between'=>'BETWEEN','not between'=>'NOT BETWEEN','notbetween'=>'NOT BETWEEN');
// 查询表达式
protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%';
// 当前SQL指令
protected $queryStr  = '';
// 参数绑定
protected $bind     =  array();
select函数:
public function select($options=array()) {
  $this->model =  $options['model'];
  $this->parseBind(!empty($options['bind'])&#63;$options['bind']:array());
  $sql  = $this->buildSelectSql($options);
  $result  = $this->query($sql,!empty($options['fetch_sql']) &#63; true : false);
  return $result;
}

로그인 후 복사

版本3.2.3经过改进之后,select精简了不少。parseBind函数是绑定参数,用于pdo查询,此处不表。

buildSelectSql()函数及其后续调用如下:

public function buildSelectSql($options=array()) {
  if(isset($options['page'])) {
    /*页码计算及处理,此处省略*/
  }
  $sql =  $this->parseSql($this->selectSql,$options);
  return $sql;
}
/* 替换SQL语句中表达式*/
public function parseSql($sql,$options=array()){
  $sql  = str_replace(
    array('%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%LOCK%','%COMMENT%','%FORCE%'),
    array(
      $this->parseTable($options['table']),
      $this->parseDistinct(isset($options['distinct'])&#63;$options['distinct']:false),
      $this->parseField(!empty($options['field'])&#63;$options['field']:'*'),
      $this->parseJoin(!empty($options['join'])&#63;$options['join']:''),
      $this->parseWhere(!empty($options['where'])&#63;$options['where']:''),
      $this->parseGroup(!empty($options['group'])&#63;$options['group']:''),
      $this->parseHaving(!empty($options['having'])&#63;$options['having']:''),
      $this->parseOrder(!empty($options['order'])&#63;$options['order']:''),
      $this->parseLimit(!empty($options['limit'])&#63;$options['limit']:''),
      $this->parseUnion(!empty($options['union'])&#63;$options['union']:''),
      $this->parseLock(isset($options['lock'])&#63;$options['lock']:false),
      $this->parseComment(!empty($options['comment'])&#63;$options['comment']:''),
      $this->parseForce(!empty($options['force'])&#63;$options['force']:'')
    ),$sql);
  return $sql;
}

로그인 후 복사

可以看到,在parseSql中用正则表达式拼接了sql语句,但并没有直接的去处理各种插叙你的数据格式,而是在解析变量的过程中调用了多个函数,此处拿parseWhere举例子。

protected function parseWhere($where) {
  $whereStr = '';
  if(is_string($where)) {   // 直接使用字符串条件
    $whereStr = $where;
  }
  else{            // 使用数组表达式
    /*设定逻辑规则,如or and xor等,默认为and,此处省略*/
    $operate=' AND ';
    /*解析特殊格式的表达式并且格式化输出*/
    foreach ($where as $key=>$val){
      if(0===strpos($key,'_')) {  // 解析特殊条件表达式
        $whereStr  .= $this->parseThinkWhere($key,$val);
      }
      else{            // 查询字段的安全过滤
        $multi = is_array($val) && isset($val['_multi']); //判断是否有复合查询
        $key  = trim($key);
        /*处理字段中包含的| &逻辑*/
        if(strpos($key,'|')) { // 支持 name|title|nickname 方式定义查询字段
          /*将|换成or,并格式化输出,此处省略*/
        }
        elseif(strpos($key,'&')){
          /*将&换成and,并格式化输出,此处省略*/
        }
        else{
          $whereStr .= $this->parseWhereItem($this->parseKey($key),$val);
        }
      }
      $whereStr .= $operate;
    }
    $whereStr = substr($whereStr,0,-strlen($operate));
  }
  return empty($whereStr)&#63;'':' WHERE '.$whereStr;
}
// where子单元分析
protected function parseWhereItem($key,$val) {
  $whereStr = '';
  if(is_array($val)){
    if(is_string($val[0])){
      $exp  =  strtolower($val[0]);
      //如果是$map['id']=array('eq',100)一类的结构,那么解析成数据库可执行格式
      if(preg_match('/^(eq|neq|gt|egt|lt|elt)$/',$exp)){
        $whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
      }
      //如果是模糊查找格式
      elseif(preg_match('/^(notlike|like)$/',$exp)){// 模糊查找,$map['name']=array('like','thinkphp%');
        if(is_array($val[1])) { //解析格式如下:$map['b'] =array('notlike',array('%thinkphp%','%tp'),'AND');
          $likeLogic =  isset($val[2])&#63;strtoupper($val[2]):'OR';  //如果没有设定逻辑结构,则默认为OR
          if(in_array($likeLogic,array('AND','OR','XOR'))){
            /* 根据逻辑结构,组合语句,此处省略*/
            $whereStr .= '('.implode(' '.$likeLogic.' ',$like).')';             
          }
        }
        else{
          $whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
        }
      }elseif('bind' == $exp ){ // 使用表达式,pdo数据绑定
        $whereStr .= $key.' = :'.$val[1];
      }elseif('exp' == $exp ){ // 使用表达式 $map['id'] = array('exp',' IN (1,3,8) ');
        $whereStr .= $key.' '.$val[1];
      }elseif(preg_match('/^(notin|not in|in)$/',$exp)){ //IN运算 $map['id'] = array('not in','1,5,8');
        if(isset($val[2]) && 'exp'==$val[2]){
          $whereStr .= $key.' '.$this->exp[$exp].' '.$val[1];
        }else{
          if(is_string($val[1])) {
             $val[1] = explode(',',$val[1]);
          }
          $zone   =  implode(',',$this->parseValue($val[1]));
          $whereStr .= $key.' '.$this->exp[$exp].' ('.$zone.')';
        }
      }elseif(preg_match('/^(notbetween|not between|between)$/',$exp)){ //BETWEEN运算
        $data = is_string($val[1])&#63; explode(',',$val[1]):$val[1];
        $whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]);
      }else{ //否则抛出异常
        E(L('_EXPRESS_ERROR_').':'.$val[0]);
      }
    }
    else{  //解析如:$map['status&score&title'] =array('1',array('gt','0'),'thinkphp','_multi'=>true);
      $count = count($val);
      $rule = isset($val[$count-1]) &#63; (is_array($val[$count-1]) &#63; strtoupper($val[$count-1][0]) : strtoupper($val[$count-1]) ) : '' ; 
      if(in_array($rule,array('AND','OR','XOR'))){
        $count = $count -1;
      }else{
        $rule  = 'AND';
      }
      for($i=0;$i<$count;$i++){
        $data = is_array($val[$i])&#63;$val[$i][1]:$val[$i];
        if('exp'==strtolower($val[$i][0])) {
          $whereStr .= $key.' '.$data.' '.$rule.' ';
        }else{
          $whereStr .= $this->parseWhereItem($key,$val[$i]).' '.$rule.' ';
        }
      }
      $whereStr = '( '.substr($whereStr,0,-4).' )';
    }
  }
  else {
    //对字符串类型字段采用模糊匹配
    $likeFields  =  $this->config['db_like_fields'];
    if($likeFields && preg_match('/^('.$likeFields.')$/i',$key)) {
      $whereStr .= $key.' LIKE '.$this->parseValue('%'.$val.'%');
    }else {
      $whereStr .= $key.' = '.$this->parseValue($val);
    }
  }
  return $whereStr;
}
protected function parseThinkWhere($key,$val) {   //解析特殊格式的条件
  $whereStr  = '';
  switch($key) {
    case '_string':$whereStr = $val;break;                 // 字符串模式查询条件
    case '_complex':$whereStr = substr($this->parseWhere($val),6);break;  // 复合查询条件
    case '_query':// 字符串模式查询条件
      /*处理逻辑结构,并且格式化输出字符串,此处省略*/
  }
  return '( '.$whereStr.' )';
}

로그인 후 복사

上面的两个函数很长,我们再精简一些来看:parseWhere首先判断查询数据是不是字符串,如果是字符串,直接返回字符串,否则,遍历查询条件的数组,挨个解析。

由于TP支持_string,_complex之类的特殊查询,调用了parseThinkWhere来处理,对于普通查询,就调用了parseWhereItem。

在各自的处理过程中,都调用了parseValue,追踪一下,其实是用了addslashes来过滤,虽然addslashes在非utf-8编码的页面中会造成宽字节注入,但是如果页面和数据库均正确编码的话,还是没什么问题的。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Windows 11 보안 센터를 끄는 방법에 대한 자세한 설명 Windows 11 보안 센터를 끄는 방법에 대한 자세한 설명 Mar 27, 2024 pm 03:27 PM

Windows 11 운영 체제에서 보안 센터는 사용자가 시스템 보안 상태를 모니터링하고 악성 코드로부터 보호하며 개인 정보를 보호하는 데 도움을 주는 중요한 기능입니다. 그러나 때로는 사용자가 특정 소프트웨어를 설치하거나 시스템 튜닝을 수행하는 경우와 같이 Security Center를 일시적으로 꺼야 할 수도 있습니다. 이 글에서는 시스템을 올바르고 안전하게 운영하기 위해 Windows 11 보안 센터를 끄는 방법을 자세히 소개합니다. 1. Windows 11 보안 센터를 끄는 방법 Windows 11에서는 보안 센터를 꺼도 작동하지 않습니다.

Windows 보안 센터에서 실시간 보호를 끄는 방법에 대한 자세한 설명 Windows 보안 센터에서 실시간 보호를 끄는 방법에 대한 자세한 설명 Mar 27, 2024 pm 02:30 PM

세계에서 가장 많은 사용자를 보유한 운영 체제 중 하나인 Windows 운영 체제는 항상 사용자들의 선호를 받아왔습니다. 그러나 Windows 시스템을 사용할 때 사용자는 바이러스 공격, 맬웨어 및 기타 위협과 같은 많은 보안 위험에 직면할 수 있습니다. 시스템 보안을 강화하기 위해 Windows 시스템에는 다양한 보안 보호 메커니즘이 내장되어 있으며 그 중 하나가 Windows 보안 센터의 실시간 보호 기능입니다. 오늘은 Windows 보안 센터에서 실시간 보호를 끄는 방법을 자세히 소개하겠습니다. 먼저,

AI의 새로운 세계 과제: 보안과 개인 정보 보호는 어떻게 되었나요? AI의 새로운 세계 과제: 보안과 개인 정보 보호는 어떻게 되었나요? Mar 31, 2024 pm 06:46 PM

생성 AI의 급속한 발전으로 인해 개인 정보 보호 및 보안에 전례 없는 문제가 발생하여 규제 개입에 대한 긴급한 요청이 촉발되었습니다. 지난 주, 저는 워싱턴 D.C.에서 몇몇 국회의원 및 그 직원들과 함께 AI가 보안과 관련된 영향에 대해 논의할 기회를 가졌습니다. 오늘날의 생성적 AI는 기초 연구, 잠재 잠재력 및 학문적 활용을 갖춘 1980년대 후반의 인터넷을 생각나게 하지만 아직 대중에게 공개될 준비가 되어 있지 않습니다. 이번에는 마이너 리그 벤처 캐피털과 트위터 에코 챔버에서 영감을 받은 자유로운 벤더 야망이 AI의 "멋진 신세계"를 빠르게 발전시키고 있습니다. "공용" 기본 모델은 결함이 있고 소비자 및 상업적 용도로 적합하지 않습니다. 만약 존재한다면 공격 표면으로 인해 체처럼 누출되는 보안 구조가 중요합니다.

Java 프레임워크 보안 아키텍처 설계는 비즈니스 요구 사항과 어떻게 균형을 이루어야 합니까? Java 프레임워크 보안 아키텍처 설계는 비즈니스 요구 사항과 어떻게 균형을 이루어야 합니까? Jun 04, 2024 pm 02:53 PM

Java 프레임워크 디자인은 보안 요구 사항과 비즈니스 요구 사항의 균형을 유지하여 보안을 가능하게 합니다. 즉, 주요 비즈니스 요구 사항을 식별하고 관련 보안 요구 사항의 우선 순위를 지정합니다. 유연한 보안 전략을 개발하고, 계층적으로 위협에 대응하고, 정기적으로 조정하세요. 아키텍처 유연성을 고려하고 비즈니스 발전을 지원하며 보안 기능을 추상화합니다. 효율성과 가용성의 우선순위를 정하고 보안 조치를 최적화하며 가시성을 향상시킵니다.

PHP는 문자열의 MD5 해시 값을 계산합니다. PHP는 문자열의 MD5 해시 값을 계산합니다. Mar 21, 2024 am 10:51 AM

이 기사에서는 PHP가 문자열의 MD5 해시 값을 계산하는 방법을 자세히 설명합니다. 편집자는 이것이 매우 실용적이라고 생각하므로 이 기사를 읽고 뭔가를 얻을 수 있기를 바랍니다. PHP에서 문자열의 MD5 해시 값 계산 소개 MD5(Message Digest 5)는 고정 길이 해시 값을 생성하는 데 사용되는 널리 사용되는 암호화 해시 함수로, 데이터 무결성 보호, 파일 무결성 확인 및 디지털 서명 생성에 자주 사용됩니다. 이 기사에서는 PHP 개발자에게 내장 함수를 사용하여 문자열의 MD5 해시 값을 계산하는 방법을 안내합니다. md5() 함수 PHP는 문자열의 MD5 해시 값을 계산하는 md5() 함수를 제공합니다. 이 함수는 문자열 매개변수를 받고 32자의 16진수 해시 값을 반환합니다.

PHP 보안 모범 사례를 구현하는 방법 PHP 보안 모범 사례를 구현하는 방법 May 05, 2024 am 10:51 AM

PHP 보안 모범 사례를 구현하는 방법 PHP는 동적 및 대화형 웹 사이트를 만드는 데 사용되는 가장 인기 있는 백엔드 웹 프로그래밍 언어 중 하나입니다. 그러나 PHP 코드는 다양한 보안 취약점에 취약할 수 있습니다. 이러한 위협으로부터 웹 애플리케이션을 보호하려면 보안 모범 사례를 구현하는 것이 중요합니다. 입력 유효성 검사 입력 유효성 검사는 사용자 입력의 유효성을 검사하고 SQL 삽입과 같은 악의적인 입력을 방지하는 중요한 첫 번째 단계입니다. PHP는 filter_var() 및 preg_match()와 같은 다양한 입력 유효성 검사 함수를 제공합니다. 예: $username=filter_var($_POST['사용자 이름'],FILTER_SANIT

Struts 2 프레임워크의 보안 구성 및 강화 Struts 2 프레임워크의 보안 구성 및 강화 May 31, 2024 pm 10:53 PM

Struts2 애플리케이션을 보호하려면 다음 보안 구성을 사용할 수 있습니다. 사용하지 않는 기능 비활성화 콘텐츠 유형 확인 활성화 입력 유효성 검사 보안 토큰 활성화 CSRF 공격 방지 RBAC를 사용하여 역할 기반 액세스 제한

C++에서 기계 학습 알고리즘 구현: 보안 고려 사항 및 모범 사례 C++에서 기계 학습 알고리즘 구현: 보안 고려 사항 및 모범 사례 Jun 01, 2024 am 09:26 AM

C++에서 기계 학습 알고리즘을 구현할 때 데이터 개인 정보 보호, 모델 변조, 입력 유효성 검사를 포함한 보안 고려 사항이 중요합니다. 모범 사례에는 보안 라이브러리 채택, 권한 최소화, 샌드박스 사용 및 지속적인 모니터링이 포함됩니다. 실제 사례에서는 Botan 라이브러리를 사용하여 CNN 모델을 암호화 및 해독하여 안전한 교육 및 예측을 보장하는 방법을 보여줍니다.

See all articles