Hi, I've developed an add-on for a non-csrf patched Plone 4.3 instance and I'm updating it so it can work with it. A couple of functional tests stop to work when the csrf patch is applied. But, curiously, it isn't due to csrf page interception.
This is the idea:
def test_blah(self):
self.login('someuser', 'somepwd')
# STEP 1: we visit a page to alter ZODB content
browser.open('someurl', 'somedata')
# it works. browser.contents shows a positive json response
# indicating that changes were made in ZODB
# STEP 2: visit another page to test for changes in ZODB
browser.open('anotherurl')
self.assertIn('blah', browser.contents)
# whith no csrf, test pass. With csrf, it doesn't.
This is a functional test (a method inside a FunctionalTestCase instance) and all steps have been made using browser.open(). Browser.open() always returned a valid page (never "Careful... executing an exploit...").
It is as if the changes in ZODB made in STEP 1 weren't preserved when the test runs with csrf patch. The page returned in STEP 2 shows valid content, but not the chages made in STEP 1.
Any idea why changes aren't preserved between step 1 and step 2?
I had the same issue, also using JSON.
The redirection to the "Careful... executing an exploit..." page works when you display HTML, but not with JSON (I guess there is a client side processing involved in plone.protect, but I haven't checked).
So your client does receive the expected JSON, but if you look in the server console, you will see a message saying the transaction will be rolled back because the Form authenticator is missing.
My solution was to change my code, so I check the request before processing it:
from plone.protect import CheckAuthenticator
class MyJSONView:
def __call__:
try:
CheckAuthenticator(self.request)
do_the_regular_thing()
except Exception, e:
self.request.response.setStatus(500)
return {'error': str(e)}
(the try .. except thing is not mandatory but I prefer my json view to returns an 500 code + a json message rather than the default Plone HTML error message)
Thank you very much! I was confused with the apparent positive response, since it was returning a JSON object. After that, I could solve it by disabling csfr for these views (they can't be exploited maliciously):
from zope.interface import alsoProvides
from plone.protect.interfaces import IDisableCSRFProtection
class MyView:
def __init__(self, context, request):
...
alsoProvides(self.request, IDisableCSRFProtection)