HTTPS 페이지에서 HTTP 콘텐츠 다루기


90

전적으로 HTTPS를 통해 액세스되는 사이트가 있지만 때로는 HTTP (주로 RSS 피드의 이미지) 인 외부 콘텐츠 를 표시 합니다. 대다수의 사용자도 IE6에 갇혀 있습니다.

이상적으로는 다음 두 가지를 모두 수행하고 싶습니다.

  • 안전하지 않은 콘텐츠에 대한 IE 경고 메시지를 방지합니다 (예 : 이미지를 아래와 같이 기본 아이콘으로 대체하여 덜 방해가되는 콘텐츠를 표시 할 수 있음).
  • 다른 방법으로는 볼 수없는 이미지 대신 사용자에게 유용한 것을 제시하십시오. JS가 있다면 어떤 이미지가로드되지 않았는지 알아 내고 대신 우리의 이미지로 대체하면 좋을 것입니다.

첫 번째 목표는 불가능하다고 생각하지만 두 번째 목표는 충분할 수 있습니다.

최악의 시나리오는 RSS 피드를 가져올 때 구문 분석하고 이미지를 로컬에 저장하여 사용자가 그런 식으로 액세스 할 수 있도록하는 것입니다.

답변:


148

최악의 시나리오는 생각만큼 나쁘지 않습니다.

이미 RSS 피드를 구문 분석하고 있으므로 이미 이미지 URL이 있습니다. 와 같은 이미지 URL이 있다고 가정 해 보겠습니다 http://otherdomain.com/someimage.jpg. 이 URL을 https://mydomain.com/imageserver?url=http://otherdomain.com/someimage.jpg&hash=abcdeafad. 이렇게하면 브라우저가 항상 https를 통해 요청하므로 문제를 제거 할 수 있습니다.

다음 부분-다음을 수행하는 프록시 페이지 또는 서블릿 만들기-

  1. 쿼리 문자열에서 url 매개 변수를 읽고 해시를 확인합니다.
  2. 서버에서 이미지를 다운로드하고 다시 브라우저로 프록시
  3. 선택적으로 디스크에 이미지 캐시

이 솔루션에는 몇 가지 장점이 있습니다. html을 만들 때 이미지를 다운로드 할 필요가 없습니다. 이미지를 로컬에 저장할 필요가 없습니다. 또한 무국적자입니다. URL에는 이미지를 제공하는 데 필요한 모든 정보가 포함되어 있습니다.

마지막으로 해시 매개 변수는 보안을위한 것입니다. 서블릿이 작성한 URL에 대한 이미지 만 제공하기를 원합니다. 따라서 URL을 만들 때 계산 md5(image_url + secret_key)하고 해시 매개 변수로 추가하십시오. 요청을 처리하기 전에 해시를 다시 계산하고 전달 된 것과 비교하십시오. secret_key는 본인 만 알고 있으므로 다른 사람은 유효한 URL을 구성 할 수 없습니다.

Java로 개발하는 경우 Servlet은 코드 몇 줄에 불과합니다. 다른 백엔드 기술에서 아래 코드를 이식 할 수 있어야합니다.

/*
targetURL is the url you get from RSS feeds
request and response are wrt to the browser
Assumes you have commons-io in your classpath
*/

protected void proxyResponse (String targetURL, HttpServletRequest request,
 HttpServletResponse response) throws IOException {
    GetMethod get = new GetMethod(targetURL);
    get.setFollowRedirects(true);    
    /*
     * Proxy the request headers from the browser to the target server
     */
    Enumeration headers = request.getHeaderNames();
    while(headers!=null && headers.hasMoreElements())
    {
        String headerName = (String)headers.nextElement();

        String headerValue = request.getHeader(headerName);

        if(headerValue != null)
        {
            get.addRequestHeader(headerName, headerValue);
        }            
    }        

    /*Make a request to the target server*/
    m_httpClient.executeMethod(get);
    /*
     * Set the status code
     */
    response.setStatus(get.getStatusCode());

    /*
     * proxy the response headers to the browser
     */
    Header responseHeaders[] = get.getResponseHeaders();
    for(int i=0; i<responseHeaders.length; i++)
    {
        String headerName = responseHeaders[i].getName();
        String headerValue = responseHeaders[i].getValue();

        if(headerValue != null)
        {
            response.addHeader(headerName, headerValue);
        }
    }

    /*
     * Proxy the response body to the browser
     */
    InputStream in = get.getResponseBodyAsStream();
    OutputStream out = response.getOutputStream();

    /*
     * If the server sends a 204 not-modified response, the InputStream will be null.
     */
    if (in !=null) {
        IOUtils.copy(in, out);
    }    
}

1
매우 건전하고 이것이 내가 함께 할 것이라고 생각합니다. 우리는 PHP를 사용하고 있지만 구현도 간단합니다. 또한 누군가가 요청할 때마다 이미지를 다운로드하고 싶지 않기 때문에 캐싱을 구현할 것입니다 (성능 및 대역폭 사용을 위해). 보안 접근 방식에 대한 제안도 건전합니다 (위와 같이 표준 보안 모델도 적용 할 것임). 제안 해 주셔서 감사합니다.
El Yobo 2010-06-17

33
이 접근 방식의 유일한 심각한 단점은 모든 외부 리소스를 자체 시스템을 통해 라우팅한다는 것입니다. 이는 책임 일뿐만 아니라 비용이 많이들 수도 있습니다.
Tim Molendijk

저는 @TimMolendijk를 두 번째로 추가하여 비용과 유지 관리를 추가 할뿐만 아니라 가까운 서버로 라우팅하거나 유휴 서버로 균형을 조정해야하는 모든 CDN을 무력화합니다.
Levente Pánczél

2
NodeJS의 솔루션은 무엇입니까?
stkvtflw

1
@TimMolendijk에 대한 또 다른 +1이지만 그렇다면 해결책은 무엇입니까? HTTPS를 통해 제공되는 사이트가 HTTP를 통해 제공되는 이미지로 제대로 재생되지 않는 것 같습니다
FullStackForger 2016 년

16

HTTPS를 통해 이미지를로드하는 빠른 솔루션을 찾고 있다면 https://images.weserv.nl/ 의 무료 역방향 프록시 서비스에 관심이있을 수 있습니다. 내가 찾던 바로 그 것이었다.

유료 솔루션을 찾고 있다면 이전에 Cloudinary.com을 사용해 보았습니다. Cloudinary.com도 잘 작동하지만이 작업에만 너무 비쌉니다.


캐치는 무엇입니까? 잘 작동합니다
Jack

5
@JackNicholson 나는 2 년 동안 비교적 무거운 부하에서 그것을 사용하고 있습니다. 잘 작동합니다! 두 개발자에게 찬사를 보냅니다.
널 (NULL)

Http로 시작하는 일부 링크 (동영상 또는 사이트)가 있는데 https 사이트의 Iframe에 표시 할 수 없습니다. 이것은 비보안 링크이므로 작동하지 않습니다. 이미지의 경우 이미지 캐시를 사용하여 문제를 해결했습니다. 누구나 어떤 생각을 가지고
INT14

@ int14 http 사이트에 대한 역방향 프록시를 설정해야합니다. AWS API Gateway와 같은 방법으로이를 수행 할 수 있습니다.
nullable

3

이것이 당신이하고있는 일에 맞는지는 모르겠지만, 빠른 수정으로 http 컨텐츠를 https 스크립트로 "래핑"할 것입니다. 예를 들어 https를 통해 제공되는 페이지에서 RSS 피드를 대체하는 iframe을 도입하고 iframe의 src 속성에 피드를 캡처하고 html을 출력하는 서버에 스크립트의 URL을 넣습니다. 스크립트는 http를 통해 피드를 읽고 https를 통해 출력합니다 (따라서 "래핑").

그냥 생각


이것이 내가 지금과 같은 상황에 처하게 될 것 같다. 이미 HTTPS 페이지에 콘텐츠를 표시하고 있습니다. 문제는 http : // src 값이있는 콘텐츠에 <img> 태그가 있다는 것입니다.이 태그는 표시되지 않고 성가신 메시지가 발생합니다.
엘 요보

예, 이미지에 대한 원본 링크를 유지하면 문제를 피할 방법이 없습니다. 래퍼 스크립트는 rss 피드 콘텐츠에서 이미지를 검색하고 제거해야합니다. 다른 의견에서 언급했듯이 팝업을 유발하는 콘텐츠를로드하지 않고 대신 정보를 표시하고 싶지 않습니다. 그것이 "중간 스크립트"의 이유입니다
hndcrftd 2010-06-14

메인 백엔드 스크립트에서 iframe 없이도이 작업을 수행 할 수 있지만이 경우에는 rss 피드가 처리되어 페이지에 출력되기 전에 돌아올 때까지 기다리고 있습니다. 페이지가 rss 피드와 비동기 적으로로드되도록 iFrame을 수행합니다. iframe을 피하기 위해 거기에 가고 싶다면 ajax 옵션도 있습니다. 궁금합니다. 백엔드 플랫폼은 무엇입니까?
hndcrftd 2010-06-14

2

두 번째 요구 사항과 관련하여 onerror 이벤트를 활용할 수 있습니다. <img onerror="some javascript;"...

최신 정보:

document.images돔에서 반복을 시도 할 수도 있습니다 . complete사용할 수 있는 부울 속성이 있습니다. 이것이 적합한 지 확실하지 않지만 조사 할 가치가있을 수 있습니다.


흥미롭게도 저는 onerror 이벤트 있다는 사실조차 몰랐습니다 . HTML을 다시 작성해야하지만 (외부 소스에서 온 것이므로) 이미 HTML 퓨리 파이어로 삭제되고 있으므로이를 필터로 추가 할 수 있습니다.
El Yobo 2010-06-14

JavaScript가 작업을 수행 하기 전에 브라우저 보안 경고가 발생 하지 않습니까?
MrWhite


0

때때로 페이스 북 앱과 마찬가지로 보안 페이지에 비보안 콘텐츠를 포함 할 수 없습니다. 또한 우리는 그 내용을 지역적으로 만들 수 없습니다. 예를 들어 iFrame에로드되는 앱은 단순한 콘텐츠가 아니므로 로컬로 만들 수 없습니다.

https에서 http 콘텐츠를로드해서는 안되며, 오류 대화 상자를 방지하기 위해 https 페이지를 http 버전으로 대체해서는 안됩니다.

사용자의 보안을 보장하는 유일한 방법은 모든 콘텐츠의 https 버전을 사용하는 것입니다. http://developers.facebook.com/blog/post/499/


3
그것은 페이스 북에서 가능할 수 있지만 모든 콘텐츠에 대해 가능하지는 않으며이 질문은 페이스 북에 관한 것이 아닙니다.
El Yobo

0

허용 된 대답은이를 PHP와 CORS 모두로 업데이트하는 데 도움이되었으므로 다른 사람들을위한 솔루션을 포함시킬 것이라고 생각했습니다.

순수 PHP / HTML :

<?php // (the originating page, where you want to show the image)
// set your image location in whatever manner you need
$imageLocation = "http://example.com/exampleImage.png";

// set the location of your 'imageserve' program
$imageserveLocation = "https://example.com/imageserve.php";

// we'll look at the imageLocation and if it is already https, don't do anything, but if it is http, then run it through imageserve.php
$imageURL = (strstr("https://",$imageLocation)?"": $imageserveLocation . "?image=") . $imageLocation;

?>
<!-- this is the HTML image -->
<img src="<?php echo $imageURL ?>" />

javascript / jQuery :

<img id="theImage" src="" />
<script>
    var imageLocation = "http://example.com/exampleImage.png";
    var imageserveLocation = "https://example.com/imageserve.php";
    var imageURL = ((imageLocation.indexOf("https://") !== -1) ? "" : imageserveLocation + "?image=") + imageLocation;
    // I'm using jQuery, but you can use just javascript...        
    $("#theImage").prop('src',imageURL);
</script>

imageserve.php CORS에 대한 자세한 내용은 http://stackoverflow.com/questions/8719276/cors-with-php-headers?noredirect=1&lq=1 참조

<?php
// set your secure site URL here (where you are showing the images)
$mySecureSite = "https://example.com";

// here, you can set what kinds of images you will accept
$supported_images = array('png','jpeg','jpg','gif','ico');

// this is an ultra-minimal CORS - sending trusted data to yourself 
header("Access-Control-Allow-Origin: $mySecureSite");

$parts = pathinfo($_GET['image']);
$extension = $parts['extension'];
if(in_array($extension,$supported_images)) {
    header("Content-Type: image/$extension");
    $image = file_get_contents($_GET['image']);
    echo $image;
}

-2

간단히 :하지 마십시오. HTTPS 페이지 내의 Http 콘텐츠는 본질적으로 안전하지 않습니다. 포인트. 이것이 IE가 경고를 표시하는 이유입니다. 경고를 제거하는 것은 어리석은 돼지 세척 방법입니다.

대신 HTTPS 페이지 에는 HTTPS 콘텐츠 있어야합니다. 콘텐츠도 HTTPS를 통해로드 될 수 있는지 확인하고 페이지가 https를 통해로드되는 경우 https를 통해 참조하십시오. 외부 콘텐츠의 경우 이는 https를 통해 사용할 수 있도록 로컬에서 요소를로드하고 캐싱하는 것을 의미합니다. 슬프게도 그럴 방법이 없습니다.

경고는 정당한 이유가 있습니다. 진지하게. 사용자 정의 콘텐츠가있는 https 표시 페이지를 어떻게 장악 할 수 있을지 5 분 동안 생각해보십시오. 놀랄 것입니다.


3
거기에는 타당한 이유가 있다는 것을 알고 있습니다. 이 점에서 IE의 동작이 FF보다 낫다고 생각합니다. 내가 목표로하는 것은 콘텐츠를로드 하지 않는 것입니다. 방해가되는 팝업 스타일 경고를 피하고 콘텐츠 대신 유용한 정보를 표시하고 싶습니다.
엘 요보

2
그럴 기회가 없습니다-나가는 동안 HTML을 다시 작성하지 않는 한. 자바 스크립트로드 후 시도가 이미 대화 상자를 표시했습니다.
TomTom

그는 단지 이미지에 대해 묻고 있었고 안전하지 않은 텍스트 나 스크립트를 요청하지 않았으므로 URL을 다시 작성하여 경고를 전달할 수 있습니다.
Jayapal Chandran 2011 년

1
대답에 변화가 없습니다. 이미지도 안전하지 않을 수 있습니다. 이것은 일반적인 것입니다. 보안 된 소스에서 나오거나 중간 공격에 의해 대체 될 수 있습니다.
TomTom 2011 년

8
"답변" 이 OP의 목표를 달성하는 방법에 대한 답변 이 아니기 때문에 비추천했습니다 .
MikeSchinkel 2014 년

-3

이것이 오래된 스레드라는 것을 알고 있지만 한 가지 옵션은 ' http : //some/image.jpg '가 '//some/image.jpg'가 되도록 이미지 URL에서 http : 부분을 제거하는 것 입니다. 이것은 CDN에서도 작동합니다.


7
이것은 때때로 작동하고 때로는 작동하지 않을 것입니다. HTTPS를 통해 업스트림 콘텐츠를 사용할 수 있는지 여부에 따라 다릅니다. 그렇지 않으면 그냥 깨질 것입니다.
El Yobo

-3

나를 위해 일하는 가장 좋은 방법

<img src="/path/image.png" />// this work only online
    or
    <img src="../../path/image.png" /> // this work both
    or asign variable
    <?php 
    $base_url = '';
    if($_SERVER['HTTP_HOST'] == 'localhost')
    {
         $base_url = 'localpath'; 
    }
    ?>
    <img src="<?php echo $base_url;?>/path/image.png" /> 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.