슈퍼 글로벌 직접 수정


20

나는 사람들 (일반적으로 좋은 코드를 작성하는 사람들) $_POST이 다음과 같은 코드로 배열을 직접 변경하는 것을 보았습니다 .

// Add some value that wasn't actually posted
$_POST['last_activity'] = time();

// Alter an existing post value
$_POST['name'] = trim($_POST['name']);

// Our pretend function
// Pass the entire $_POST array as data to work with in the function
// The function update_record() will read only the values we actually need
update_record($_POST);

// ...That sure was easier than creating a new array 
//  with only the $_POST values we actually need.

예를 들어 update_record()$ _POST에 직접 액세스해서는 안되므로 예를 들어 다른 데이터 배열을 전달할 수 있지만 게 으르거나 디자인이 잘못되었거나 잘못되었을 수 있습니다. 그러나 우리는 여전히 유효한 배열을에 전달하고 update_record()있습니다. 왜 새로운 배열을 생성합니까?

이것은 질문의 요점이 아니며 사용법의 예일뿐입니다. 그러나 많은 사람들이 이것이 $_REQUEST데이터 로 수행되어서는 안된다고 말하는 것을 들었습니다 . 그런데 왜? 무해 해 보입니다.

예 :

  • $_GET실제로 존재하지 않는 기본 (또는 포스트) 값 설정

  • $_POST양식 제출 후 실제로 게시되지 않은 값 추가

  • 스크립트 초기에 $_GET배열 값 또는 키를 직접 위생 처리 또는 필터링합니다 (대체 위생 ... 왜 그렇지 않습니까?)

  • $_POST양식 제출 전에 수동으로 값을 설정하여 입력을 기본값으로 채 웁니다 (입력이 기본값을 읽으면 $_POST이 작업을 수행함)

  • 당신의 자신의 $_SERVER가치를 만들어? 물론이지?

  • 어떻게 같은 다른 약 $_COOKIE$_SESSION? 물론 우리는 그것들을 직접 수정해야합니까? 그렇다면 왜 다른 사람들은 그렇지 않습니까?

수정 지시해야 슈퍼 전역은 결코 수행되지, 또는에서 할 OK입니다 어떤 경우?


# 1, # 2 및 # 3에 예기치 않은 사용법 (특히 # 1 및 # 2)이 있기 때문에 동의합니다.
Kevin Peno

좋은 질문. 전역 값을 사용하는 것과 같은 방식으로 전역 배열 수정이 잘못되었습니다. 또한이 배열은 코드 내에서 엉망이되는 직접적인 방법을 변경하는 목적 (외부에서 매개 변수 전달)을 가지고 있습니다. 그러나이 배열 중 일부는 코드 내에서 문제를 일으키지 않기 위해 스크립트를 시작하면서 위생 처리 될 수 있다고 생각합니다.
Tadeck

1
OO 입력 배열 래퍼 (암시 적 필터링)를 사용하고 있는데 $ _GET 또는 $ _POST 변수가 변조되면 추가 알림을 인쇄합니다. 여전히 가능하지만 좁은 상황으로 제한되어야합니다. (크로스 모듈 시그널링, 디스패처 / 프론트 컨트롤러 만 필요하지만)
mario

@mario : 나는 더 당신이 성취 방법에 대해 듣고 싶어요 당신은이 질문에 대해 살펴 취할 수있는 경우 : stackoverflow.com/questions/12954656
웨슬리 Murch

답변:


16

PHP가 이미 슈퍼 글로벌을 설정하고 있다는 점을 감안하면, 그것들을 수정하는 것이 하다고 생각하지 않습니다 . 경우에 따라 문제를 해결하는 가장 좋은 방법 일 수 있습니다. 특히 쉽게 수정할 수없는 타사 코드를 처리 할 때 특히 그렇습니다. ( $_GET직접 사용 하거나 일부 키가 등에 있다고 가정 할 수 있습니다 $_SERVER.)

그러나 일반적으로 말하자면, 자신의 코드를 작성할 때 나쁜 습관이라고 생각합니다. $_REQUEST모든 페이지에서 자동으로 실행되는 장면 필터 뒤의 일부 데이터를 수정하면 부작용이 발생할 수 있습니다. "마법 인용 부호"가 증명을 위해 야기한 모든 문제를 참조하십시오.

따라서 그렇게하지 않으면 (수퍼 글로벌을 자동으로 필터링) 다음과 같은 이점이 없습니다.

$_POST['foo'] = filter($_POST['foo']);

쉽게 할 수있을 때 :

$foo = filter($_POST['foo']);

나는 그 사이트 전체 구분을하는 것이 훨씬 더 명확하다고 생각 $_POST하고 $_GET있습니다 항상 신뢰할 수없는 데이터를 어지러움을 없애기 위해, 그들은해야 결코 그대로 사용하지.

필터링 된 값을 다른 변수에 복사하면 "내가하는 일을 이해합니다 ...이 입력을 필터링했으며 사용하기에 안전합니다"라는 주장을합니다.


의견을 보내 주셔서 감사합니다. 인터넷은 거의 2 일 동안 사용되었으므로 아무에게도 답장을 드릴 기회가 없었습니다. 이 예에서는 $ _POST를 수정하여 업데이트 함수에 전달할 데이터 배열로 사용했습니다.이 함수에서 읽을 다른 $ _POST 키가 몇 개 있다고 가정합니다. 나는 새로운 배열을 만드는 것을 선호하지만 사람들이 대신 이것을하는 것을 보았으므로 여전히 그것을 "나쁜 코드"라고 부를 지 확신 할 수 없지만 적어도 그런 식으로 기울어지고 있다고 생각합니다. 나는 당신이 이것을 할 필요성을 느낄 때마다 항상 더 좋은 방법이 있다고 생각합니다.
웨슬리 머치

1
@Wesley가 "나쁜"주된 이유는 일부 사용자 데이터를 삭제하는 것을 잊게 될 가능성이 훨씬 높기 때문입니다. 예제에서 하나의 키를 수정 한 다음 전체 배열을 전달합니다. 해당 데이터 중 일부에 처리되지 않은 악성 입력이 포함되어 있으면 어떻게됩니까? 새로운 배열을 손으로 직접 작성하고 필요한 것만 복사하여 $_POST위생 처리 하는 것이 좋습니다 . 그리고 다른 사람들이 이것을하는 것에 관해서는 ... 많은 사람들이 매우 나쁜 PHP 코드를 작성하지만, 그것은 당신에게도 변명의 여지가 없습니다. :)
konforce

데이터를 위생 처리하는 것 외에 다른 초 세계적 학대 애플리케이션을 강조했을 것입니다. 나는 아마도 그것을 완전히 배제하고 더 명확한 질문을 썼을 것입니다. 사람들은 특히 보안 측면을 선택하고 나머지는 무시합니다. 고맙게 들리지 않기 때문에 피드백에 감사드립니다. 나는 당신이 좋은 점을 언급했지만 질문이 새로운 3 분 동안 투표 파티를 놓쳤으므로 언젠가 기다릴 것입니다.
웨슬리 머치

9

일반적으로 사전 정의 된 수퍼-글로벌을 수정하여 소독 된 데이터와 원시 / 신뢰할 수없는 데이터가 무엇인지 명확하게 수정하지 말 것을 제안합니다.

다른 사람들은 요청주기가 시작될 때 슈퍼 글로벌을 정리하면 다른 곳에서는 걱정할 필요가 없다고 제안 할 수 있습니다.

필요할 때 항상 일치시킵니다.

$id = (int)$_POST['id'];

또는 유사합니다.

다른 변수의 관점에서 그것의에 쓸 수 없습니다에 좋은 연습이다 $_GET, $_POST, $_REQUEST, $_SERVER또는 $_COOKIE. $_SESSION그러나 세션에 데이터를 쓰려는 경우가 많으므로 세션의 여러 요청에 걸쳐 지속됩니다.


2
이런 종류의 전역이 사라질 필요가있는 더 많은 이유는 필요할 때 얻을 수있는 객체 / 방법으로 대체되어야합니다. 왜 setcookie존재하지만 우리는 통해 쿠키를 얻 $_COOKIE습니까? 또한 $_COOKIE현재 세션이 시작될 때만 설정되고 업데이트되지 않으므로 코드의 후반 영역에 최신 정보가 표시되도록 두 영역에서 쿠키를 변경 / 설정해야합니다.
Kevin Peno

고마워 제임스, 나는 잠시 동안 오프라인 상태에 있었기 때문에 응답 할 수 없었습니다. 긴 이야기를 짧게 만들기 위해-나는 당신에게 동의합니다. post / get / etc에 쓰는 것보다 항상 더 나은 해결책이 있지만, " 이 작업을 수행하지 마십시오 "에서와 같이 엄격하게 나쁜 생각으로 간주되는지 확실하지 않습니다 . 따라서이 유형의 코드를 다시 살펴보면 조잡한 코드에서 "호출"할 권리가 있다고 생각합니까, 아니면 때로는 영리하고 안전한 방식으로 사용할 수 있습니까?
웨슬리 머치

@Wesley 만약 이것이 "이제 절대로하지 않는다면"슈퍼 글로벌은 아마도 읽기 전용 일 것입니다. 나는 단지 이유 때문에 응용 프로그램 코드에서 그것들을 설정하거나 덮어 쓰는 것은 나쁜 습관이라고 부릅니다.
Michel Feldheim

3

피해야합니다. 어쩌면 당신이 무언가를 위생 처리하는 것을 잊었을 때 위험한 데이터를 검색 할 수 있습니다. 소독하는 동안 데이터를 새로운 구조로 복사하는 경우

  • 당신은 단지 당신이 원하는 것 / 필요하지 않은 것을 얻 $_POST습니다.
  • 새로 생성 된 배열에 일부 키가 없거나 전혀없는 경우 오류가 발생합니다.

다른 스크립트는 배열이 손대지 않고 호기심을 가질 수 있다고 가정 할 수 있습니다.


2

슈퍼 글로벌을 수정하는 아이디어가 잘못되었습니다. 더 좋은 방법이있을 것입니다 뭔가를하는 빠른 해키 방법입니다.

$_POST예를 들어 의 값을 변경하면 소프트웨어가 그렇지 않은 데이터를 받았다고 말하는 것입니다.

실제 문제

이것이 큰 문제가되는 실제 상황이 있습니다.

팀에서 일하고 있다고 상상해보십시오. 이상적인 세상에서는 모든 사람이 같은 구문을 사용하지만 이상적인 세상에는 살지 않습니다. 한 개발자 인 John은을 사용하여 게시 된 데이터에 액세스하는 것을 좋아합니다 $_POST. 그는 포스트 변수에서 무언가를 바꿉니다.

$_POST['ranking'] = 2; // John has changed ranking from 1 to 2 for whatever reason

그런 다음 다른 개발자 인 Chris가 filter_input 사용자가 조작 할 수있는 데이터를 처리 할 때 소프트웨어를 보호하기 위해 입력 된 (예 : GET, POST, SERVER, COOKIE) 데이터에 액세스 가 있습니다. 소프트웨어 부분에서의 가치를 얻어야합니다 ranking. 코드의 그의 부분은 John 's 이후 입니다.

$ranking = filter_input(INPUT_POST, 'ranking', FILTER_SANITIZE_NUMBER_INT);
// $ranking = 1

위의 예에서, 슈퍼 글로벌을 변경함으로써 PHP가 깨졌습니다. John은 $_POST['ranking']어떤 이유로 든 값 을 2로 설정 했지만 이제 Chris는 값 1을 받았습니다.

내가 할 수있는 다른 방법을 보지 못했을 때 :

AWS로드 밸런서 뒤에서 wordpress를 블로그로 사용하는 프로젝트를 진행했습니다. 이것은의 가치를 변경$_SERVER['remote_address'] . 이 경우 다른 개발자는 다음을 수행 할 수밖에 없었습니다.

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $_SERVER['REMOTE_ADDR'] = $parts[0];
}

결론

슈퍼 글로벌을 바꾸는 것보다 더 좋은 방법이 거의 있습니다


1

여기서 중요한 질문은“테마를 왜 수정해야합니까?”입니다. 그럴만한 이유가 없습니다. 대치 소독을해야한다면 지역 변수를 사용하는 것이 좋습니다…

코드 길이가 짧지 않으면 (예 : 50 줄 미만) 슈퍼 글로벌을 수정하면 코드를 유지 관리 및 해체하기가 더 어려워집니다.

그런데 $ _POST를 함수에 전달할 필요가 없습니다. 함수의 로컬 범위 내에서도 액세스 할 수있는 초 전역 배열이기 때문입니다.


3
그러나 그는 그것을 통과 해야 합니다. 다른 가능한 매우 테스트 하드 및되지는 해킹 (심지어 이보다) 어떤없이 다른 값으로 함수 / 메소드를 호출합니다
KingCrunch

글쎄, 그것은 그의 방법에 따라 다릅니다. $ _POST 배열의 내용을 구문 분석하기 위해 설계된 경우에는 전달할 필요가 없습니다. 물론 그것이 당신이 옳은 것보다 더 일반적인 / 추상적 인 목적을 제공한다면.

2
@Thomas, 나는 King에 동의합니다. 그것들이 전역 적 일지라도, 다른 범위 내에서 전역적인 것을 사용해서는 안됩니다. 왜냐하면 그것은 긴밀한 결합을 유발하기 때문입니다 (이 때문에 함수를 재사용 할 수 없습니다). 예를 들어, 데이터를 삭제하는 기능이 데이터를 삭제하는 이유는 $_POST무엇입니까? 전달 $_POST하면 함수가 모든 데이터를 삭제 합니다 .
케빈 페노

0

슈퍼 글로벌을 수정할 이유가 없다고 말하면서이 질문에 처음 대답 한 후, 나는 결정한 시간의 예를 들어이 답변을 편집하고 있습니다.

나는 현재 URL 재 작성 데이터베이스 테이블에서 작업하고 있습니다. request 열이 사용자를 해당 열로 안내합니다 target.

예를 들어,이 request수도 blog/title-here와 그target 수도 있습니다 blog.php?id=1.

변수 blog.php를 기대하고 $_GET있고를 변경하고 싶지 않기 때문에 header("Location:")다음과 같이하고 있습니다.

$uri    = explode('?', $uri_request)[0];
$params = explode('?', $uri_request)[1];
parse_str($params, $_GET);

이것은 $_GET전달 된 의도 된 매개 변수를 포함 하는 배열을 만듭니다 .target열에 .

궁극적으로, 나는 당신이 절대로하지 않으면 슈퍼 글로벌을 수정 하지 말 것을 강력히 권합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.