How to stop a user from opening a new browser session in XPages

梦想的初衷 提交于 2019-12-08 02:13:33

问题


I have a front end document locking process that creates an Application Scope variable with the UNID/Username/time in it, then a timer that updates this information every 30 seconds. If someone tries opening the document to edit I check (using the UNID) to see if anyone else has the document. If the time is greater than 30 seconds I cancel the lock and allow the new user to open it.

I have considered do something similar with a database 'lock' which is pretty simple but I need a unique Identifier of the browser session. I can build the applicationScope variable using ReplicaID/UserName/time but I need one more piece of information that will identify this browser session.

Is there such a piece of information available somewhere? Something like a browser sessionID?


回答1:


You want to allow only one open browser window/tab per user and database.

For every XPage you open in browser you have to test if the same database is open in another browser window/tab already. If so, decline opening XPage with e.g. redirecting to an error XPage.

It is impossible to do this on server side only as the server don't know in which browser tab an Xpage gets opened.

So, the server needs client's help. The client have to give the server a unique browser window/tab id.

A browser window/tab doesn't have a unique id. But, opening a new window/tab we can create an random id and store it in browsers sessionStorage. This is a unique storage for every window/tab.

This window/tab id can be send to server with a partial refresh GET and stored on server for the user in an application scope variable.

Also, the server has to know when a window/tab gets closed so that the same database can be opened in another window/tab. For this the client has to tell the server "I am alive" every X seconds.

This is the complete solution:

Create a Custom Control "UniqueBrowserTab"

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:eventHandler
        event="onClientLoad"
        submit="false">
        <xp:this.script><![CDATA[
            var secondsIamAliveInterval = 5;
            var tabId = sessionStorage.getItem("tabId");
            if (!tabId) {
                tabId = Math.random();
                sessionStorage.setItem("tabId", tabId);
            }
            function sendTabIdToServer() {
                XSP.partialRefreshGet("#{id:browserTabControl}", {
                    params: {'tabId': tabId}
                });
            }
            sendTabIdToServer();
            setInterval(function() {
                sendTabIdToServer();
            }, secondsIamAliveInterval * 1000);
        ]]></xp:this.script>
    </xp:eventHandler>
    <xp:panel id="browserTabControl">
        <xp:this.rendered><![CDATA[#{javascript:
            var secondsIgnoreOtherSession = 7;
            if (param.tabId) {
                var userName = session.getEffectiveUserName();
                var userData = applicationScope.get(userName);
                var now = new Date().getTime();
                if (userData) {
                    if (userData.tabId !== param.tabId) {
                        if (userData.time + secondsIgnoreOtherSession*1000 > now) {
                            context.redirectToPage("Error.xsp");
                        }
                    }
                } 
                applicationScope.put(userName, {tabId : param.tabId, time: now});
            }
            return true
        }]]></xp:this.rendered>
    </xp:panel>
</xp:view>

Include the Custom Control "UniqueBrowserTab" into every XPages or e.g. into application layout's Custom Control.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:xc="http://www.ibm.com/xsp/custom">
    <xc:UniqueBrowserTab />
    ...
</xp:view>

Create an XPage Error.xsp wich has not included the Custom Control "UniqueBrowserTab".

This will allow only one browser window/tab per database for a user across all browsers.




回答2:


There is the SessionID cookie which is unique for the browser. I believe it's passed as part of the partial refresh information.

Just bear in mind that the SessionID would be the same for multiple windows of the browser. I'm not sure if that is an issue.




回答3:


Thanks to all that have posted here. In actual fact there are two similar but different issues.

In the first instance it is to block multiple instances of the application in the same browser, and Sven's post answers that one.

The second issue is opening the same application in multiple browsers. In this case I am going to use an applicationScope variable appSession which is a Map with the key being UserName~DBRepID then two 'fields'

Time which is refreshed by a Client Side timer event which updates the time every "N" seconds. sessionID = facesContext.getExternalContext().getRequest().getSession().getId();

In the before page loads (perhaps as a PhaseListener ??) I lookup appSession with the key UserName~RepID if the sessionID matches open the page. if the Time in appSession is time expired then set the time to the current time and set the sessionID to the current getID() and open the page. If not then open error page. The sessionID has to have a timer on it so that if the user closes the browser or tab it will eventually time out. I'm using something like this for an XPage Document locking routine and it works well.

I have not put this all together yet but it looks to me as if it should get the job done. If anyone see a better way to do this I would be happy to hear.



来源:https://stackoverflow.com/questions/27426273/how-to-stop-a-user-from-opening-a-new-browser-session-in-xpages

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!