I want to add user session support to my application. Since reloading the page will restart the application and even opening another browser tab will cause the original one 'out of sync' problem.
Do I need to create an independent window for each login, or is there any plugin I can use, or if I make it a Spring + Vaadin application, will it solve this problem?
Applications created with Vaadin Framework are automatically statefull, so your application should keep its state unless you have the ?restartApplication parameter in the URL.
To support multible browser tabs / windows in the same session, the getWindow(String name) must be overriden in the Application class to return a new Window instance for each browser tab / window:
#Override
public Window getWindow(String name) {
// If the window is identified by name, we are good to go
Window w = super.getWindow(name);
// If not, we must create a new window for this new browser window/tab
if (w == null) {
w = new CalcWindow();
// Use the random name given by the framework to identify this
// window in future
w.setName(name);
addWindow(w);
// Move to the url to remember the name in the future
w.open(new ExternalResource(w.getURL()));
}
return w;
}
For more information about Vaadin's multi window support, see this wiki page.
Reloading the page should not restart the application, unless your url ends with ?restartApplication=true.
The Application object is stored in the HTTP Session, therefore everything you want to store per user can be associated with the application.
Typically, each browser process can only support one HTTP Session, hence you will only be able to support one user per browser (unless you make significant efforts, and store per-user state on each application level Window. I recommend you don't do this unless you know what you are doing : one user-per-http-session is the norm in web applications)
Spring+Vaadin are a good combination - I am using this pairing to great effect in our projects - but are not particularly useful in this context.
Vaadin does not support multiple-windows/tabs in it's default configuration (hence your out-of-sync errors). However, it is trivial to write the code to do so : here's a simple explanation, and some code
Related
Our application has been developed on Liferay with multiple Spring MVC portlets on the page. Its a single page application, and the navigation only happens inside the portlets. Now sometimes when Liferay session times out and I send a request to the control for a new view, the liferay login page is being shown inside the portlet. But the expected behaviour is if the liferay session is timed out, then the whole page should have redirected to Login page.
I have specified following properties in the portal-ext.properties
session.timeout.warning=1
session.timeout.auto.extend=false
session.timeout.redirect.on.expire=true
browser.cache.signed.in.disabled=true
Any suggestions?
If you're just doing Ajax navigation in the portlets, you might want to hook into Liferay's session-extension way (you'd have to look it up - there's a client side timer that counts down and displays the "session.timeout.warning" - I can't give pointers right now)
Alternatively, if a session extension is acceptable as long as a browser window is open, you can use the same mechanism to show an alternative behaviour: Instead of willingly timing out a session, it can extend the session. See portal(-ext).properties:
#
# Set the auto-extend mode to true to avoid having to ask the user whether
# to extend the session or not. Instead it will be automatically extended.
# The purpose of this mode is to keep the session open as long as the user
# browser is open and with a portal page loaded. It is recommended to use
# this setting along with a smaller "session.timeout", such as 5 minutes for
# better performance.
#
session.timeout.auto.extend=true
Does this happen in all your pages or only on specific pages. ?
Does this happen on click of any button?
If so , do the following in the method that you are calling on the click of the button,
function onClickFunction(){
var liferaySession = Liferay.Session._currentTime;
if(liferaySession == '0'){
//reload page
}
else{
//proceed
}
}
How can you detect the url that I am browsing in chrome/safari/firefox via cocoa (desktop app)?
As a side but related note, are there any security restrictions when developing a desktop app that the user will be alerted and asked if they want to allow? e.g. if the app accesses their contact information etc.
Looking for a cocoa based solution, not javascript.
I would do this as an extension, and because you would like to target Chrome, Safari, and Firefox, I'd use a cross-browser extension framework like Crossrider.
So go to crossrider.com, set up an account and create a new extension. Then open the background.js file and paste in code like this:
appAPI.ready(function($) {
appAPI.message.addListener({channel: "notifyPageUrl"}, function(msg) {
//Do something, like send an xhr post somewhere
// notifying you of the pageUrl that the user visited.
// The url is contained within msg.pageUrl
});
var opts = { listen: true};
// Note: When defining the callback function, the first parameter is an object that
// contains the page URL, and the second parameter contains the data passed
// to the context of the callback function.
appAPI.webRequest.onBeforeNavigate.addListener(function(details, opaqueData) {
// Where:
// * details.pageUrl is the URL of the tab requesting the page
// * opaqueData is the data passed to the context of the callback function
if(opaqueData.listen){
appAPI.message.toBackground({
msg: details.pageUrl
}, {channel: "notifyPageUrl"});
}
}, opts ); // opts is the opaque parameter that is passed to the callback function
});
Then install the extension! In the example above, nothing is being done with the detected pageUrl that the user is visiting, but you can do whatever you like here - you could send a message to the user, you could restrict access utilizing the cancel or redirectTo return parameters, you could log it locally utilizing the crossrider appAPI.db API or you could send the notification elsewhere, cross-domain, to wherever you like utilizing an XHR request from the background directly.
Hope that helps!
And to answer the question on security issues desktop-side, just note that desktop applications will have the permissions of the user under which they run. So if you are thinking of providing a desktop app that your users will run locally, say something that will detect urls they access by tapping into the network stream using something like winpcap on windows or libpcap on *nix varieties, then just be aware of that - and also that libpcap and friends would have to have access to a network card that can be placed in promiscuous mode in the first place, by the user in question.
the pcap / installed desktop app solutions are pretty invasive - most folks don't want you listening in on literally everything and may actually violate some security policies depending on where your users work - their network administrators may not appreciate you "sniffing", whether that is the actual purpose or not. Security guys can get real spooky so-to-speak on these kinds of topics.
The extension via Crossrider is probably the easiest and least intrusive way of accomplishing your goal if I understand the goal correctly.
One last note, you can get the current tab urls for all tabs using Crossrider's tabs API:
// retrieves the array of tabs
appAPI.tabs.getAllTabs(function(allTabInfo) {
// Display the array
for (var i=0; i<allTabInfo.length; i++) {
console.log(
'tabId: ' + allTabInfo[i].tabId +
' tabUrl: ' + allTabInfo[i].tabUrl
);
}
});
For the tab API, refer to:
http://docs.crossrider.com/#!/api/appAPI.tabs
For the background navigation API:
http://docs.crossrider.com/#!/api/appAPI.webRequest.onBeforeNavigate
And for the messaging:
http://docs.crossrider.com/#!/api/appAPI.message
And for the appAPI.db stuff:
http://docs.crossrider.com/#!/api/appAPI.db
Have you looked into the Scripting Bridge? You could have an app that launches, say, an Applescript which verifies if any of the well known browser is opened and ask them which documents (URL) they are viewing.
Note: It doesn't necessarily need to be an applescript; you can access the Scripting Bridge through cocoa.
It would, however, require the browser to support it. I know Safari supports it but ignore if the others do.
Just as a quick note:
There are ways to do it via AppleScript, and you can easily wrap this code into NSAppleScript calls.
Here's gist with AppleScript commands for Safari and Chrome. Firefox seems to not support AE.
Well obviously this is what I had come across on google.
chrome.tabs.
getSelected
(null,
function
(tab) {
alert
(tab.url);
}) ;
in pure javascript we can use
alert(document.URL);
alert(window.location.href)
function to get current url
I am working on a multi-threaded WTL-based application that opens multiple browser windows, each with its own embedded IWebBrowser2 instance for the browsing, and each in a separate UI thread.
In response to NewWindow3, I open a new browser-window, and return the new window's IWebBrowser2->get_Application() which returns an IDispatchPtr.
While the popup does open the desired site, the session in the original window, from which this popup was opened, EXPIRES - any further navigation in that original window takes be back to the login page!
Some points that I thought may be important for anyone to help me -
This happens ONLY when the NewWindow3 is fired, with a non-empty bstrUrlContext (the 3rd parameter containing the originating URL)
As part of the NewWindow3 processing, the following done -
Creation of the new IWebBrowser2-embedding window, Create()'ed with zWindowName set to the value of the bstrUrlContext parameter
The returned IDispatch pointer is retrieved from IWebBrowser2->get_Application()
This issue has been resolved.
I had to create the IWebBrowser2-embedding window with an empty-string (_T("")) WindowName.
And had to ensure creation of the IWebBrowser2 control by invoking CAxWindow::CreateControl() in the window's OnCreate() handler (for WM_CREATE)
Thanks
I'm trying to register my application that will handle opening of links, e,g, http://stackoverflow.com. I need to do this explicitly for Windows 8, I have itworking in earlier versions of Windows. According to MSDN this has changed in Win8.
I've been through the Default Programs page on MSDN (msdn.microsoft.com/en-us/library/cc144154.aspx) page on MSDN. It provides a great walkthrough on handling file types but is light on details for protocols. Registering an Application to a URL Protocol only goes over the steps involved in setting up a new protocol, but not how to correctly add a new handler to an existing protocol.
I've also tried the registry settings outlined in other SO posts.
One more thing, the application is not a Metro/Windows Store App, so adding an entry in the manifest won't work for me.
You were on the right track with the Default Programs web page - in fact, it's my reference for this post.
The following adapts their example:
First, you need a ProgID in HKLM\SOFTWARE\Classes that dictates how to handle any input given to it (yours may already exist):
HKLM\SOFTWARE\Classes
MyApp.ProtocolHandler //this is the ProgID, subkeys are its properties
(Default) = My Protocol //name of any type passed to this
DefaultIcon
(Default) = %ProgramFiles%\MyApp\MyApp.exe, 0 //for example
shell
open
command
(Default) = %ProgramFiles%\MyApp\MyApp.exe %1 //for example
Then fill the registry with DefaultProgram info inside a Capabilities key:
HKLM\SOFTWARE\MyApp
Capabilities
ApplicationDescription
URLAssociations
myprotocol = MyApp.ProtocolHandler //Associated with your ProgID
Finally, register your application's capabilities with DefaultPrograms:
HKLM\SOFTWARE
RegisteredApplications
MyApplication = HKLM\SOFTWARE\MyApp\Capabilities
Now all "myprotocol:" links should trigger %ProgramFiles%\MyApp\MyApp.exe %1.
Side note since this is a top answer found when googling this kind of an issue:
Make sure the path in the shell command open is a proper path to your application.
I spent an entire day debugging issue that seemed only to affect Chrome and Edge on Windows 10. They never triggered the protocol handler while Firefox did.
What was the issue? The path to the .bat file used mixed
\ and / slashes.
Using only proper \ slashes in the path made Edge & Chrome suddenly able to pick up the request.
LaunchUriAsync(Uri)
Starts the default app associated with the URI scheme name for the specified URI.
You can allow the user to specify, in this case.
http://msdn.microsoft.com/library/windows/apps/Hh701476
// Create the URI to launch from a string.
var uri = new Uri(uriToLaunch);
// Calulcate the position for the Open With dialog.
// An alternative to using the point is to set the rect of the UI element that triggered the launch.
Point openWithPosition = GetOpenWithPosition(LaunchUriOpenWithButton);
// Next, configure the Open With dialog.
// Here is where you choose the program.
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
options.UI.InvocationPoint = openWithPosition;
options.UI.PreferredPlacement = Windows.UI.Popups.Placement.Below;
// Launch the URI.
bool success = await Windows.System.Launcher.LaunchUriAsync(uri, options);
if (success)
{
// URI launched: uri.AbsoluteUri
}
else
{
// URI launch failed. uri.AbsoluteUri
}
This is a weird bug, and I'm not even sure how to begin figuring out what's going on.
We are using Cake 1.3.8 with our sessions in the database. I am not using ACL or any other access control. If we navigate into the application and click around a bit, and then rapidly click the browser back button twice (I've tried in Firefox and Chrome) the user is logged out more often than not and receives the error message 'You are not authorized to access that location'.
All of my searches thus far have involved people wanting to make the page inaccessible if a user logged out and then used the back button. I'm not seeing anything reported with regards to the issue I'm seeing.
Does anybody know if this is a Cake issue or have any thoughts on debugging what is going wrong?
Update: I found where the problem is. I have the security set to high, because we need the session to be closed whenever somebody closes the browser. I also have the timeout set very high because we do large binary uploads to S3, and don't want the user logged out while it's uploading or downloading. The specific block of code in cake_sessions.php that's causing the problem is:
$time = $this->read('Config.time');
$this->write('Config.time', $this->sessionTime);
if (Configure::read('Security.level') === 'high') {
$check = $this->read('Config.timeout');
$check -= 1;
$this->write('Config.timeout', $check);
if (time() > ($time - (Security::inactiveMins() * Configure::read('Session.timeout')) + 2) || $check < 1) {
$this->renew();
$this->write('Config.timeout', 10);
}
}
$this->valid = true;
I would guess this is because session IDs are regenerated between requests when security = high. Source:
http://book.cakephp.org/compare/44/CakePHP-Core-Configuration-Variables/cakephp/cakephp1x
You only need one out of sync request, say for a missing image and you will lose the session. I've generally found it unworkable because it's not possible to prevent users double-clicking on links and buttons and invalidating their session.
I would think about using medium security, setting the session timeout fairly short and using an AJAX script to refresh the session at regular intervals (eg every 60s). That way the user will be logged out quickly if the tab/window is closed.
If security is a priority I would suggest hacking the core to make sure the session cookies are set to http_only to help guard against session hijacking by XSS attacks. Cakephp 1.x supports PHP4 so probably isn't setting this by default.
http://php.net/manual/en/function.setcookie.php
It's possible that the session is erased and before it can be written again, the back button is clicked removing the auth from the session variables.
Page loads -> Back Button Clicks -> sessions is erased (but before session is rewritten) -> Back button clicks -> Session checks no existing session.
The only thing that I can think is happening is that when you're going back a page too quickly your code can't validate the person quickly enough (round trip from checking credentials) and throws an error that gets displayed on the next page that is loaded (second backed-to page).
Are you sure the person is actually logged out, or is it just the error being thrown?
Without seeing any code, it will be difficult to nail it down any further.