Handling of multiple logged-in Wiki instances broken by new JDK cookie manager
PeterBowman opened this issue · 5 comments
JDK cookies are used in Wiki.java since 61eba0f (0.34). The default CookieStore implementation manages cookies on a system-wide manner, which means that URL connections handled by multiple Wiki.java instances are consequently overriden (i.e. each new Wiki.java instance makes all previously created instances re-use its cookies).
I noticed this while running an app that queries two distinct wikis through the same account. My bot user has bot rights on plwiktionary, hence I configure an assertion as shown below:
Wiki plwikt = Wiki.createInstance("pl.wiktionary.org");
plwikt.login("User", "password");
plwikt.setAssertionMode(Wiki.ASSERT_USER | Wiki.ASSERT_BOT);
plwikt.getSiteStatistics(); // fine
Wiki ruwikt = Wiki.createInstance("ru.wiktionary.org");
ruwikt.login("User", "password");
ruwikt.setAssertionMode(Wiki.ASSERT_USER);
ruwikt.getSiteStatistics(); // fine
plwikt.getSiteStatistics(); // error
A java.lang.AssertionError: Assertion that the user has the "bot" right failed.
is thrown after the last line. The cookies set by plwikt
on initialization and later login are overriden by the ruwikt
instance, and in fact, I don't have bot permissions on ruwiktionary.
A similar example will lead to the same result with non-bot accounts: log in with the first Wiki.java instance as a regular user, set the assertion, and don't log in through the second instance.
An alternative approach that helps to reproduce this bug involves using two accounts:
Wiki user1 = Wiki.createInstance("test.wikipedia.org");
user1.login("User1", "password1");
user1.setAssertionMode(Wiki.ASSERT_USER);
user1.edit("Sandbox", "1", "1"); // correct, performed by User1
Wiki user2 = Wiki.createInstance("test.wikipedia.org");
user2.login("User2", "password2");
user2.setAssertionMode(Wiki.ASSERT_USER);
user2.edit("Sandbox", "2", "2"); // correct, performed by User2
user1.edit("Sandbox", "1?", "1?"); // WRONG, performed by User2
I tried https://stackoverflow.com/a/17513786. The assertion issue seems solved, but I get a FailedLoginException in the dual-user sample snippet upon logging in with user2
:
result=Aborted
reason=Cannot log in when using MediaWiki\Session\BotPasswordSessionProvider sessions.
Perhaps something like this could restore the old grabCookies
mechanism and avoid setting the system-wide cookie handler:
wiki-java/src/org/wikipedia/Wiki.java
Line 486 in bd1b122
Perhaps something like this could restore the old grabCookies mechanism and avoid setting the system-wide cookie handler:
Done in my fork at PeterBowman@a95d5c8 and seems to solve this. Since it's more of a copy-paste of your former code, @MER-C, I'd like to ask if this solution is robust enough. I'm not familiarized with the reasons behind that grabCookies
implementation. Also, I have incidentally restored a previous TODO notice.
Reproduced with the following:
Wiki testWiki = Wiki.createInstance("test.wikipedia.org");
Wiki enWiki = Wiki.createInstance("en.wikipedia.org");
enWiki.getPageText("Main Page");
// should still be logged in...
testWiki.setAssertionMode(Wiki.ASSERT_USER);
testWiki.getPageText("Main Page");
I've gone for a slightly modified StackOverflow solution that shoves as much onto the JDK as possible. Please reopen if the commit doesn't fix the bug.
Thanks PeterBowman for issuing this bug. Updated to 0.34 and my bot suddenly broke because of this.