登录/注销后强制所有页面访问刷新/清除缓存

问题描述 投票:0回答:4

我的网站完全由动态数据构建,其中一些数据会根据用户身份验证而发生变化。当用户“登录”该网站时,我会在页面导航栏中显示他们的新状态及其用户名。但是,当他们在身份验证之前访问最近访问过的页面(后退按钮等)时,该页面的导航栏版本将不会刷新。有哪些方法可以强制浏览器刷新页面?反之亦然:如果用户注销,最近的页面仍会显示已通过缓存版本进行身份验证。

我可以使用什么技术来始终强制网站上任何页面上的浏览器端刷新/清除缓存?

谢谢。

Nb:服务器端我使用 eXist-db 4.7 的

login:set-user()
通过控制器对用户进行身份验证(即“登录”)。

javascript html css xquery exist-db
4个回答
3
投票

我建议您查看this线程,以获取一些更具体的信息,但总结一下:

  • 您需要检查loginState是否改变了
  • 如果出现则需要刷新页面

解决方案1)

步骤1

您需要像这样初始化一个全局变量:

let loginStateChanged = false;

当用户登录或注销时,您会:

loginStateChanged = true;

步骤2

您需要监听“浏览器后退按钮事件”,并在登录状态发生变化时刷新窗口。

您可以像这样使用

pageshow
事件:

window.addEventListener('pageshow', (event) => {
    var isBackNavigation = event.persisted || 
        (typeof window.performance != 'undefined' && window.performance.navigation.type === 2);

    // If the navigation type is a back navigation, and the login
    // State has changed, refresh the window
    if (isBackNavigation && loginStateChanged) {
        window.location.reload(); // reload the page
    }
});

或者使用 jQuery;

$(window).on('popstate', () => {
    // If the login State has changed, refresh the window
    if (loginStateChanged) {
        window.location.reload(); // reload the page
    }
});

由于窗口刷新,

loginStateChanged
将重置为默认值
false

解决方案2)

或者如果您需要实现多个选项卡的解决方案:

步骤1

改用 localStorage 和全局变量:

let isLoggedIn = JSON.parse(localStorage.getItem('isLoggedIn')); // Get the initial value
isLoggedIn = isLoggedIn != 'undefined' ? isLoggedIn : false; // If initial value is undefined, set it to false

当用户登录或注销时,您会:

isLoggedIn = /* login: true, logout: false */; // update global variable
localStorage.setItem('isLoggedIn', JSON.stringify(isLoggedIn)); // update localStorage variable

步骤2

window.addEventListener('pageshow', (event) => {
    var isBackNavigation = event.persisted || 
        (typeof window.performance != 'undefined' && window.performance.navigation.type === 2);

    // If the navigation type is a back navigation, and the login 
    // State has changed, refresh the window
    // Here you check, if the localStorage variable is different, than the global variable
    if (isBackNavigation && JSON.parse(localStorage.getItem('isLoggedIn')) != isLoggedIn) {
        window.location.reload(); // reload the page
    }
});

解决方案3)

如果您想在任何后退或前进单击时刷新,只需使用以下代码:

window.addEventListener('pageshow', (event) => {
    var isNavigation = event.persisted || 
        (typeof window.performance != 'undefined' && window.performance.navigation.type === 2);
    if (isNavigation) {
        window.location.reload();
    }
});

解决方案 3 测试文件:

test1.html 和 test2.html(它们完全相同):

<html>
    <head>
        <title>test</title>
        <script>
            window.addEventListener("pageshow", function ( event ) {
                var isNavigation = event.persisted || 
                    (typeof window.performance != 'undefined' && window.performance.navigation.type === 2);

                console.log("Is navigated through button? ", isBackNavigation);
                if (isNavigation) {
                    alert("reload!");
                    window.location.reload();
                }
            });
        </script>
    </head>
    <a href="test1.html">Test1</a>
    <a href="test2.html">Test2</a>
</html>

每次导航操作都会刷新整个页面。在打开新选项卡时,它无论如何都会重新加载。


2
投票

我为您的问题找到的最佳来源是以下博客文章,它以我也能理解的方式解释了缓存:https://jakearchibald.com/2016/caching-best-practices/

TLDR: 不要尝试在客户端修复此问题,让服务器来处理此问题。 在服务器端添加以下响应头:

Cache-Control: no-cache

2
投票

@MauriceNino 已经涵盖了几乎所有的技术方法,尽管在某些场景下还存在一种。

不是最好的解决方案,但如果您的所有页面都是使用带有参数的某些动态网址创建的,您只需添加一个新参数“v”或“version”=随机登录会话密钥。

要实现这一点,所有和任何 URL(您不想缓存的)都应与上述参数连接。创建一个集中的方法来调用ajax或pages并添加这个

version
参数。每次登录时都会创建一个新的唯一参数。如果参数更改,浏览器将始终发出新请求。

尽管这样做的缺点是你的 URL 不会很漂亮。您所有的网址都必须经过过滤器(我猜您已经有了)


0
投票

我改编了@MauriceNino的解决方案:我只是检查帐户是否发生变化(以避免显示用户注销或登录不同帐户后可能不适用的数据)。您甚至可以考虑在 HTML 页面上设置当前的 Unix 时间戳或其他一些变量,您可以在 JavaScript 中检查和比较这些变量,以帮助决定是否需要刷新。

// Browsers show the previous state when clicking "back", even if the page is expired.
// If the user signs out or signs into another account and then clicks back,
// this code will reload the page.
// It can't be handled server side since no HTTP request is sent when the user clicks "back"
// The only other way is to disable the client cache (no-store)
    window.addEventListener('pageshow', (event) => {
        try {
            var account_id = document.getElementById("account_id").val();
            var isBackNavigation = event.persisted ||
                (typeof window.performance != 'undefined' && window.performance.navigation.type === 2);
            // If user just clicked "back" and the account_id in the HTML is
            // different from local storage, refresh the page.
            if (isBackNavigation && JSON.parse(localStorage.getItem('account_id')) != window.account_id) {
                window.location.reload();
            } else {
                localStorage.setItem('account_id', JSON.stringify(account_id));
            }
        } catch(e) {
            console.log(e)
        }
    });

注意事项:

  • 如果禁用本地存储,它将不起作用,因此您可以考虑使用 cookie。
  • 在页面重新加载之前有一段时间,上一页仍然显示,但至少它可以防止用户使用“过时”的内容。
  • 仅当用户 account_id 更改然后单击“后退”时才会重新加载。
© www.soinside.com 2019 - 2024. All rights reserved.