저도 같은 문제를 겪었는데, Google로 로그인할 때에도 이런 현상이 발생합니다. WordPress 이전에는 Nginx를 리버스 프록시로 사용했습니다. 이 문제가 관련이 있을까요?
이 문제는 WordPress에 Discourse 사이트를 통해 로그인할 때 발생하는 것으로 추정됩니다. 그렇다면 WordPress에서 생성된 nonce가 만료된 것이 원인이 됩니다. 이는 Object Caching이 활성화된 WordPress 사이트에서 발생하는 현상입니다.
해결 방법 중 하나는 “Login With Discourse” 링크가 있는 페이지에서 Object Cache를 비활성화하는 것입니다. 이 방법을 사용할 경우, 익명 사용자를 위한 Object Cache가 비활성화되어 있는지 확인하세요.
또 다른 해결 방법은 여기에 나와 있습니다: Wordpress SSO Expired nonce - #15 by simon. 해당 게시물에 있는 함수는 그대로 복사하여 WordPress 테마의 functions.php 파일에 붙여넣을 수 있습니다.
해당 함수는 Login With Discourse URL에 랜덤 문자열을 추가합니다. 이 랜덤 문자열은 WordPress가 캐시를 무효화하고 사용자에게 새로운 nonce를 생성하도록 트리거합니다. @angus님, 이 부분은 플러그인 코드에 추가되어야 할 것 같습니다: wp-discourse/lib/sso-client/sso-client-base.php at main · discourse/wp-discourse · GitHub. 이로 인한 단점은 없으며, 각 방문 시마다 새 nonce를 생성하는 대신 object caching으로 인해 오래된 nonce가 사용되는 문제를 해결할 다른 방법이 없다고 생각합니다.
답변 주셔서 감사합니다. Discourse를 실서비스로 전환하면 WordPress 사이트에서 Nginx 캐시를 비활성화해 보겠습니다. 그래도 해결되지 않으면 설명에 따라 functions.php 파일을 수정하겠습니다.
감사합니다 @simon!
보통 URL에 랜덤 문자열을 추가하는 것은 브라우저의 캐시를 우회하기 위한 용도이므로, 이것이 왜 WordPress의 객체 캐시(object cache)를 비우게 되는지 정확히 이해가 되지 않습니다. WordPress의 객체 캐시에 캐싱되는 쿼리가 무엇인가요? 해당 방식이 작동할 수 있는 객체 캐시와 무관한 다른 이유를 발견했습니다.
만약 그것이 사실이라면, 약간 다른 조정(tweak)이 필요할 수도 있습니다. 하지만 제가 무언가를 놓치고 있는 걸까요?
제가 아는 바로는 문제가 WordPress 객체 캐시 자체에 있는 것이 아닙니다. 객체 캐시는 기본적으로 요청(request) 간에 영속적(persistent)이지 않으니까요. 문제는 어떤 형태로든 영속적 캐싱이 활성화된 사이트에서 발생합니다: https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-caching. 이 기능은 플러그인을 통해 설정할 수 있지만, 일부 호스팅 제공업체(예: WP Engine)에서는 기본적으로 활성화되어 있습니다. WP Engine의 경우, 로그인 페이지에서는 객체 캐시를 활성화하지 않지만, 다른 모든 페이지에서는 익명 사용자를 대상으로 활성화하는 것으로 보입니다. 따라서 WP Engine에서는 “Discourse로 로그인” 링크가 로그인 페이지가 아닌 다른 페이지에 추가될 때만 문제가 발생합니다.
discourse_sso_url의 문제는 이 값이 항상 동일하게 설정되어 있을 때, 영속적 캐싱이 활성화된 사이트에서는 항상 동일한 nonce를 반환한다는 점입니다. discourse_sso 값을 기본값인 1 대신 무작위 문자열로 설정하면 캐시가 무효화됩니다. 이전에 테스트했을 때 항상 이렇게 작동했습니다. 현재는 테스트할 수 있도록 설정되어 있지 않습니다.
수정: 이 문제에 대한 추가 세부 사항은 여기에 있습니다: Discourse (as provider) + WP SSO nonce error - #14 by simon. 이 문제를 확인한 지 꽤 오래되었습니다. 당시 이 문제를 해결하기 위한 방법은 discourse_sso_url에 무작위 문자열을 추가하는 것 과 로그인 링크가 표시되는 페이지에서 페이지 캐싱이 활성화되지 않도록 확인하는 것(반드시 두 가지를 모두 해야 함)이었습니다. (그렇지 않으면 익명 사용자가 방문할 때마다 무작위 문자열이 고유하지 않게 됩니다.)
알겠습니다. 설명해 주셔서 감사합니다.
여기서 수정 사항을 적용할 때 그것이 "다양성(pluralistic)"을 유지할지, 즉 다른 캐싱 방식과도 함께 작동할지 확실하지 않으므로, 신중을 기해야 할 것 같습니다. 따라서 한 단계씩 진행하는 것이 좋겠습니다.
또한, 이 특정 문제를 일으키는 다양한 캐시의 역할에 대해, 특히 영속 객체 캐시와 페이지 캐시(존재하는 경우)의 역할 차이점에 대해 아직 명확하지 않습니다. 페이지 캐시가 이 문제를 일으킬 수 있는 이유는 이해할 수 있지만, 영속 객체 캐시는 아직 그렇지 않습니다. 만약 후자(영속 객체 캐시) 때문이라면, 대신 Nonce 클래스의 쿼리를 조정해야 할 수도 있습니다.
다음 주에 이 부분을 좀 더 깊이 있게 테스트해 봐야 할 것 같습니다.
@Petr_Mišák 로그인 링크가 있는 페이지에서 사용 중인 페이지 캐싱을 먼저 비활성화해 보고 그 결과를 알려주시겠어요?
WordPress의 테스트 로그인 페이지에서 Nginx Microcache를 비활성화해 보겠습니다. Discourse를 통해 WordPress에 로그인하는 테스트 페이지는 여기 있습니다: Test Discourse Login | Svět Androida
Google 로그인을 사용하여 로그인할 때 간헐적으로 문제가 발생하는 것을 발견했습니다.
먼저 캐싱 문제가 없는지 확인해 주세요. 그 후 진행 상황이 어떻게 되는지 알려주시면 됩니다.
알겠습니다. 단계별로 해결해 나가겠습니다. 동의합니다.
공식 로그인에서도 동일한 오류가 발생하는 것 같습니다. 직접 테스트해 보실 수 있도록 시뮬레이션할 이메일을 보내드립니다.
- Přihlásit se ‹ Svět Androida — WordPress 페이지로 이동하세요.
- "Discourse로 로그인"을 선택하고 Google 계정을 사용하세요.
- Discourse 로그인이 완료되면 https://www.svetandroida.cz/ 또는 https://www.svetandroida.cz/wp-login.php로 다시 리디렉션되며 오류 메시지가 표시됩니다. 스크린샷을 참고하세요.
이 문제는 항상 발생하지 않기 때문에 테스트가 잘 이루어지지 않았습니다.
Nginx 캐시를 비활성화하기 전에 오류가 발생하는지 확인해 주시고 알려주시면 감사하겠습니다.
https://www.svetandroida.cz/wp-login.php에서 Nginx Microcache의 상태를 확인해 보았지만, 해당 사이트에서는 Nginx Microcache가 전혀 사용되지 않는 것으로 보입니다. 따라서 “만료된 nonce” 문제는 다른 요인과 관련이 있을 것입니다.
Petr_Mišák 님, 이 문제의 원인을 찾았는지 확인차 연락드립니다.
우리는 검색을 해 보았지만, 안타깝게도 아직까지 성과가 없습니다. 하지만 계속 검색을 이어가며 문제의 원인을 찾아보겠습니다.
Přihlásit se ‹ Svět Androida — WordPress에서 저희 Nginx Microcache의 상태를 확인해 보았지만, 그곳에서는 Nginx Microcache가 전혀 사용되지 않는 것으로 보입니다.
https://www.svetandroida.cz/에 Discourse를 통해 로그인하는 문제와 nonce가 캐시되는 것이 관련이 있다고 확신합니다. 이를 테스트한 방법은 “Discourse로 로그인” 링크(https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F)를 클릭하는 것이었습니다.
처음 그렇게 했을 때 https://komunita.svetandroida.cz/로 리디렉션되었고, Gmail로 Discourse 사이트에 계정을 생성한 후 로그인된 사용자로 WordPress 사이트로 다시 리디렉션되었습니다.
그 후 WordPress 사이트에서 로그아웃하고 “Discourse로 로그인” 링크를 다시 클릭하여 다시 로그인하려고 했습니다. 이번에는 “만료된 nonce” 오류가 발생했습니다.
그 후 discourse_sso URL 매개변수에 무작위 값을 가진 로그인 링크를 생성하여, 예를 들어 https://www.svetandroida.cz/?discourse_sso=181253058&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F와 같이 설정했을 때, Discourse를 통해 WordPress 사이트에 아무 문제 없이 로그인할 수 있었습니다.
이것을 몇 번이나 시도해 보았는데, 플러그인이 생성하는 로그인 링크(https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F)와 discourse_sso 매개변수에 무작위 값이 설정된 로그인 링크를 모두 사용했습니다. 반환되는 nonce가 최소 몇 분 동안은 캐시되는 것으로 보입니다.
문제를 완전히 디버깅하지는 않았지만, 테마의 functions.php 파일에 다음을 추가하기만 하면 작동하도록 만들 수 있다고 확신합니다(이는 discourse_sso URL 매개변수에 무작위 문자열을 설정합니다. 로그인 페이지에 "페이지 캐싱"이 또한 활성화되어 있지 않은 한 작동해야 합니다.)
add_filter('wpdc_sso_client_query', 'wpdc_custom_sso_client_query' );
function wpdc_custom_sso_client_query() {
return wp_generate_password( 12, false );
}
문제를 디버깅하고 싶다면, 성공적인 요청에서 제가 보고 있는 내용은 다음과 같습니다. Cache-Svetzitrka: STALE 라인을 주목하십시오. 이는 커스텀 캐싱 레이어가 존재하고 성공적인 요청에 대해 캐시가 STALE 상태였다는 것(즉, 새로운 nonce가 생성되었음)을 나타낼 수 있습니다.
요약
Request URL:
https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F
Request Method:
GET
Status Code:
302 Found
Remote Address:
93.185.102.156:443
Referrer Policy:
strict-origin-when-cross-origin
Cache-Control:
max-age=0
Cache-Svetzitrka:
STALE
Content-Length:
0
Content-Type:
text/html; charset=UTF-8
Date:
Mon, 11 Dec 2023 09:38:05 GMT
Expires:
Mon, 11 Dec 2023 09:21:47 GMT
Location:
https://komunita.svetandroida.cz/session/sso_provider?sso=bm9uY2U9MGU3NTNjYWNhNjMwNmMzNzM5M2MyODk4MjZlYzMxMjQmcmV0dXJuX3Nzb191cmw9aHR0cHMlM0ElMkYlMkZ3d3cuc3ZldGFuZHJvaWRhLmN6JTJG&sig=32ddcc85bd2dd7175f963e791cc9ac734a607355d773422d3abec6173c9f656b
Server:
nginx
Strict-Transport-Security:
max-age=10886400; includeSubdomains; preload
X-Content-Type-Options:
nosniff
X-Frame-Options:
SAMEORIGIN
X-Redirect-By:
WordPress
실패한 요청에서 제가 보고 있는 내용은 다음과 같습니다. Cache-Control: no-cache, no-store 라인은 응답이 캐시되어서는 안 될 것임을 나타내는 것 같지만, 응답의 from service worker 항목은 응답이 서비스 워커의 캐시에서 올 수 있음을 나타냅니다.
요약
Request URL:
https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F
Request Method:
GET
Status Code:
302 Found (from service worker)
Referrer Policy:
strict-origin-when-cross-origin
Cache-Control:
no-cache, no-store
Content-Security-Policy:
upgrade-insecure-requests; base-uri 'self'; object-src 'none'; script-src https://komunita.svetandroida.cz/logs/ https://komunita.svetandroida.cz/sidekiq/ https://komunita.svetandroida.cz/mini-profiler-resources/ https://komunita.svetandroida.cz/assets/ https://komunita.svetandroida.cz/extra-locales/ https://komunita.svetandroida.cz/highlight-js/ https://komunita.svetandroida.cz/javascripts/ https://komunita.svetandroida.cz/plugins/ https://komunita.svetandroida.cz/theme-javascripts/ https://komunita.svetandroida.cz/svg-sprite/ https://www.google-analytics.com/analytics.js https://www.googletagmanager.com/gtag/js 'sha256-8uAKDaK4QxxCeYZl0Wxad2Nnj2tgKyA14hYBh66pnn0='; worker-src 'self' https://komunita.svetandroida.cz/assets/ https://komunita.svetandroida.cz/javascripts/ https://komunita.svetandroida.cz/plugins/; frame-ancestors 'self'; manifest-src 'self'
Content-Type:
text/html; charset=utf-8
Date:
Mon, 11 Dec 2023 09:38:05 GMT
Discourse-Logged-Out:
1
Location:
https://komunita.svetandroida.cz/login
Referrer-Policy:
strict-origin-when-cross-origin
Server:
nginx
Set-Cookie:
sso_payload=sso%3Dbm9uY2U9MGU3NTNjYWNhNjMwNmMzNzM5M2MyODk4MjZlYzMxMjQmcmV0dXJuX3Nzb191cmw9aHR0cHMlM0ElMkYlMkZ3d3cuc3ZldGFuZHJvaWRhLmN6JTJG%26sig%3D32ddcc85bd2dd7175f963e791cc9ac734a607355d773422d3abec6173c9f656b; path=/; SameSite=Lax
Set-Cookie:
_forum_session=kGW2K6gafsjS90qQMEmxzjggEYo4tZPZe76XZNVro34ilyuuHsaYt2nEzC9h6tfiSBmY9XoDdxh1SV3S8n%2BwqrbsD58UvJBz6khjm%2Fty83ufkgry8daHDdyoTfFwQOjAbXrWeGIwkS4edGY1XetNwXhu%2FNJUghqmq8BEUycBt7098KUO%2BmRYDl5iSL0FNhUzo5Hc7xwRg0tfxuxmb%2FIyVLnbFz6IJuGB3Y95PRcU5DYIwAAny1GQbKQ23kSjgALxAThG7aA%2B7LCI9cJNWV1JRSy%2FTElDN3iugKuVpaQcrSPhV3SvQaiNH3MCfLwu6yxlp%2BZ%2BwTyw22czX8bb197z36WhlbghYtxvKYGRjONJQUagisjPpMrCAcGeTKsGB4JgnUKCtlrwIoFvaDxjec7hMo3aCnibbbkmcxWc6LvD6G2xaxkDgebe7RpvfTYdG8cn8j6rNwX3hM8la4RqZnmma0%2FQlSrfj0BjfY7lnan6TYm28vLwH%2FFfdZoRbo6JdTs5AFjCJvx9UXSjFmoXHH1R1yfAizPeKDFnpiuUs4a%2FBzWafQ%3D%3D--8PEvbWwpqBuJMSRJ--CzzhBea4mmv58a7KLEnukw%3D%3D; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie:
_t=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax
Strict-Transport-Security:
max-age=31536000
Vary:
Accept
X-Content-Type-Options:
nosniff
X-Discourse-Route:
session/sso_provider
X-Download-Options:
noopen
X-Frame-Options:
SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
none
X-Request-Id:
001750b9-94f2-4bf0-8503-9d673463b91e
X-Runtime:
0.012335
X-Xss-Protection:
0



