Programing

외부 소스 (예 : Excel, Word 등)에서 링크를 클릭 할 때 쿠키가 인식되지 않는 이유는 무엇입니까?

lottogame 2020. 12. 4. 07:43
반응형

외부 소스 (예 : Excel, Word 등)에서 링크를 클릭 할 때 쿠키가 인식되지 않는 이유는 무엇입니까?


Excel 또는 Word와 같은 웹 브라우저에서 외부에서 링크를 클릭하면 동일한 브라우저 창의 새 탭에서 링크가 열리더라도 세션 쿠키가 처음에 인식되지 않는 것으로 나타났습니다.

브라우저는 결국 쿠키를 인식하지만 Excel 또는 Word의 초기 링크가 작동하지 않는 이유에 대해 의아해합니다. 더 어렵게 만들기 위해 링크를 클릭하면 Outlook에서 제대로 작동합니다.

왜 이런 일이 일어나는지 아는 사람이 있습니까? PHP 5.3에서 Zend Framework를 사용하고 있습니다.


이는 MS Office가 Hlink.dll 구성 요소를 사용하여 링크가 Office 문서인지 다른 것인지 조회하기 때문입니다. MS Office는 IE6의 Hlink.dll 구성 요소를 사용하여 외부 브라우저의 도움없이 문서 내에 링크 된 문서를 열 것으로 예상합니다.

세션 쿠키가 웹 사이트를 보호하는 경우 Hlink는 자연스럽게 로그인 페이지로 리디렉션되고 HTML 페이지에 도달하여 "이해"할 수 없으며 외부 브라우저에서 열립니다. 원래 URL (예상 동작)이 아니라 302 리디렉션 인 경우에도 리디렉션의 결과가 열립니다.

마이크로 소프트는 대신 그들이 버그 인식, 지원되지 않는 구성 요소 (가 Hlink.dll)에서 해당 버그가 우리의 머리에 뒤집어을 하고 업그레이드하기를 거부 (우리가 사용하는 SSO 시스템, 즉 세션 쿠키의 결함이라고 우리를 설득하려고). MS Office 의 조회 기능해제하는 해결 방법을 제공합니다 .

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
  Office\9.0\Common\Internet\ForceShellExecute:DWORD=1

또는 HTTP 리디렉션을 방지하고 Javascript 리디렉션 또는 META REFRESH 리디렉션으로 변경 (예 : Hlink가 원본 URL에서 텍스트 / html 페이지를 가져와 외부 브라우저를 실행하여 처리하도록 함)를 방지하기 위해 서버 측 해결 방법을 제공합니다.


우리는 이와 동일한 문제가 있었고 레일을 사용하는 사람들을 돕기 위해 오픈 소스 gem을 작성했습니다 : https://github.com/spilliton/fix_microsoft_links

하지만 모든 프레임 워크에서 사용한 것과 동일한 접근 방식을 사용할 수 있습니다.

  1. 사용자 에이전트가 Microsoft 제품의 것인지 감지
  2. 브라우저가 올바른 쿠키로 페이지를 새로 고치게하는 메타 새로 고침 태그로 빈 html 페이지를 렌더링합니다.

예제 코드 : https://github.com/spilliton/fix_microsoft_links/blob/master/lib/fix_microsoft_links.rb


서버 측 이것은 IIS에서 나를 위해 일했습니다 (다시 쓰기 규칙 사용)

<rule name="WordBypass" enabled="true" stopProcessing="true">
    <match url=".*" />
    <conditions>
        <add input="{HTTP_USER_AGENT}" pattern="Word|Excel|PowerPoint|ms-office" />
    </conditions>
    <action type="CustomResponse" statusCode="200" statusReason="Refresh" statusDescription="Refresh" />
</rule>

다음은 위의 spilliton의 답변을 기반으로 한 C # ASP.NET 솔루션입니다. Global.asax.cs에서 다음을 추가합니다.

    private static string MSUserAgentsRegex = @"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)";
    protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch(Request.UserAgent, MSUserAgentsRegex))
        {
            Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>");
            Response.End();
        }
    }

VB.NET 수정 :

Dim userAgent As String = System.Web.HttpContext.Current.Request.UserAgent

If userAgent.Contains("Word") Or userAgent.Contains("Excel") Or userAgent.Contains("PowerPoint") Or userAgent.Contains("ms-office") Then
       System.Web.HttpContext.Current.Response.Clear()
       System.Web.HttpContext.Current.Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>")
       System.Web.HttpContext.Current.Response.End()
End If

기본적으로 브라우저가 페이지를 새로 고치도록 강제하므로 요청이 브라우저의 사용자 에이전트 및 모든 올바른 쿠키와 함께 들어옵니다.


PHP 솔루션 :

이렇게하면 MS 제품이 리디렉션을 인식하지 못합니다. 따라서 MS는 필요한 링크에서 브라우저를 시작합니다.

if (isset($_SERVER['HTTP_USER_AGENT']))
{
    $http_user_agent = $_SERVER['HTTP_USER_AGENT']; 
    if (preg_match('/Word|Excel|PowerPoint|ms-office/i', $http_user_agent)) 
    {
        // Prevent MS office products detecting the upcoming re-direct .. forces them to launch the browser to this link
        die();
    }
}

..이 코드 다음에 리디렉션


1. 엑셀 / 단어 포인트에서 http://example.com/from_excel.php로

2. "from_excel.php"에서 세션을 사용하는 페이지로 리디렉션

<script>document.location.href = "http://example.com/page_with_session.php"; </script>

MS Word에서 URL을 클릭하면 두 개의 Chrome 탭이 열리고 열리는 페이지에 JavaScript 리디렉션이있는 문제가 있습니다. window.location.href=blabla

서버 측에서 디버깅하여 Chrome 외에 Office 앱에서 보낸 요청이 있음을 확인했습니다. 이것은 너무 이상합니다.

그러나 어쨌든 요청 헤더 "User-Agent"를 확인하고 빈 페이지를 Office 앱에 반환함으로써 두 개의 탭 문제가 해결되었습니다. 그것은 확실히 옳은 일입니다!


여기 WordPress에서 이에 대한 해결책이 있습니다. 이것을 테마 또는 다른 플러그인 파일의 functions.php에 추가하십시오.

이는 WP와 같은 시스템이 로그 아웃 한 사용자를 액세스하려는 페이지로 리디렉션하는 로그인 페이지로 보내는 경우 유용 할 수 있습니다. Word에서 사용자를이 페이지로 보냈지 만 사용자가 이미 로그인 한 경우 WP가 제대로 처리하지 못했습니다.이 코드는 현재 사용자가 있고 redirect_to 매개 변수가 전달되었는지 확인합니다. 그렇다면 redirect_to 위치로 리디렉션됩니다.

function my_logged_in_redirect_to()
{
global $current_user;

if($current_user->ID && $_REQUEST['redirect_to'])
{           
    wp_redirect($_REQUEST['redirect_to']);
    exit;
}
}
add_action('wp', 'my_logged_in_redirect_to');

Excel 용 VBA 수정 사항은 다음과 같습니다. Microsoft Word에도 동일한 개념을 적용 할 수 있습니다. 기본적으로 Excel 내에서 링크를 시작하는 대신 코드는 셸 내에서 링크를 실행합니다. 코드는 다음과 같습니다.

Private Sub Worksheet_FollowHyperlink(ByVal objLink As Hyperlink)
    Application.EnableEvents = False
    Dim strAddress As String
    strAddress = "explorer " & objLink.TextToDisplay
    Dim dblReturn As Double
    dblReturn = Shell(strAddress)
    Application.EnableEvents = True
End Sub
  1. 링크가 포함 된 Excel 시트의 경우 시트 탭을 마우스 오른쪽 버튼으로 클릭하고 코드보기를 클릭 합니다. VBA 편집기가 나타납니다.
  2. 창에 코드를 붙여넣고 편집기를 닫습니다.
  3. 페이지의 각 링크를 수정하여 해당 링크가있는 셀을 다시 가리 키도록합니다. 이렇게하려면 :
  4. 링크를 마우스 오른쪽 버튼으로 클릭하고 하이퍼 링크 편집을 클릭 합니다. 하이퍼 링크 편집 창이 나타납니다.
  5. 이 문서에 배치를 클릭합니다 .
  6. 시트 이름을 클릭합니다.
  7. 대한 셀 참조를 입력 , 셀 참조 (예 : A4)를 입력합니다.
  8. 클릭 OK .

몇 가지 참고 사항 :

  • 스프레드 시트를 매크로 사용 스프레드 시트 (.xlsm)로 저장해야합니다. 사용자가 스프레드 시트를 열면 매크로를 활성화하라는 메시지가 표시됩니다. 아니요라고 대답하면 링크가 작동하지 않습니다.
  • 이 지침은 Excel 2010을 기반으로합니다. 아마도 이후 버전도 비슷할 것입니다.

나는 그들이 이것을 기능이라고 부르는 것을 믿을 수 없습니다. 그러나 다음은 Apache의 기능 수정입니다.

RewriteEngine On

# Send a 200 to MS Office so it just hands over control to the browser
# It does not use existing session cookies and would be redirected to the login page otherwise
# https://www.wimpyprogrammer.com/microsoft-office-link-pre-fetching-and-single-sign-on/

RewriteCond %{HTTP_USER_AGENT} ;\sms-office(\)|;)
RewriteRule .* - [R=200,L]

Might not be best performance wise, as the whole page gets sent instead of an empty response, but I did not want to add another Apache modules just for fixing such an idio^H^H^H^H feature.


Here is an example of the fix using a dotnet core middleware:

public class MicrosoftOfficeLinksHandlingMiddleware
{
    private static readonly Regex MsUserAgentsRegex = new Regex(@"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)");
    private readonly RequestDelegate _next;

    public MicrosoftOfficeLinksHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        string userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();

        if (userAgent != null && MsUserAgentsRegex.IsMatch(userAgent))
        {
            // just return an empty response to the office agent
            return;
        }

        await _next(context);
    }
}

I had to solve this issue for an ASP.NET site but I only wanted to use javascript/ jQuery:

var isCoBrowse = ('<%= Session["user"].ToString().ToLower() %>' != '0');
if (isCoBrowse && window.location.href.indexOf('ReturnUrl=') >= 0 && window.location.href.indexOf('dllCheq') == -1) {
    //redirect to the ReturnUrl & add dllCheq to the URI
    var toRedirect = decodeURIComponent(gup('ReturnUrl', window.location.href)) + '&dllCheq';
    window.location = toRedirect;
}

I got the gup function from: How to get the value from the URL parameter?


Use fix provided by microsoft given link below. https://support.microsoft.com/en-us/kb/218153


Here is how to workaround this with Java and Spring via a Filter:

/**
 * To see why this is necessary, check out this page:
 * https://support.microsoft.com/en-gb/help/899927.
 */
public class MicrosoftFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(final HttpServletRequest request,
      final HttpServletResponse response,
      final FilterChain filterChain) throws ServletException, IOException {
    //Serve up a blank page to anything with a Microsoft Office user agent, forcing it to open the
    //URL in a browser instead of trying to pre-fetch it, getting redirected to SSO, and losing
    //the path of the original link.
    if (!request.getHeader("User-Agent").contains("ms-office")) {
      filterChain.doFilter(request, response);
    }
  }
}

/**
 * Security configuration.
 */
@Configuration
public class SecurityConfiguration {
  @Bean
  public FilterRegistrationBean microsoftFilterRegistrationBean() {
    FilterRegistrationBean<MicrosoftFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new MicrosoftFilter());
    registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return registrationBean;
  }
}

NGINX solution below:

if ($http_user_agent ~* Word|Excel|PowerPoint|ms-office) {
    return 200 '<html><head><meta http-equiv="refresh" content="0"/></head><body></body></html>';
}

You can put it in the server or location block. Works like charm.


I suspect this is a matter of how you are setting the cookie(s).

Due to the nature of how the web was created, example.com is not seen as the same domain as www.example.com; hence: you can be logged in at www.example.com and not logged in at example.com.

So in other words, check the URL in your word or excel file - is it the same domain as how you are logged in within your browser?

There are two fixes/solutions to this cookie inconsistency: 1. redirect anyone who tries to load your site without the www. to the same page with the www. (or vice versa), or 2. when you are setting the cookie, make sure to specify the domain argument as ".example.com". The leading dot indicates the cookie should be valid on all subdomains of that domain as well.

I suspect the reason the browser eventually recognizes it is because you probably eventually end up landing on a URL with the same domain structure as how you are logged in.

Hope this helps.

참고URL : https://stackoverflow.com/questions/2653626/why-are-cookies-unrecognized-when-a-link-is-clicked-from-an-external-source-i-e

반응형