The code I'm working with has the following lines in the OnSessionStart function in Application.cfc:
<cfcookie name="CFID" value="#SESSION.CFID#" />
<cfcookie name="CFTOKEN" value="#SESSION.CFTOKEN#" />
On my LocalHost, these lines trigger an error ("Element CFID is undefined in SESSION") the first time I try to load the app. But then when I refresh, it loads normally.
On the deployed environments (DEV and PROD), it works fine, without an error.
I've looked through the code, and determined that these cookies are never read explicitly by the code, so I commented them out in my LocalHost. This eliminated the error on my LocalHost -- but when I deployed the change to DEV it prevented the LDAP authentication from completing (even though it had completed successfully on LocalHost). Therefore, I had to reverse the change.
Which brings us to the question: How can I eliminate the error in my LocalHost without compromising the login process in DEV and PROD? (Certainly I can live with the error if I must -- but a consistent code base that works identically and reliably in both places is much more desirable.)
I'm very comfortable debugging the code -- but I suspect this issue has something to do with the configuration, and I don't really know where to start beyond the simple experiments I've done above.
Points that may be useful to others with more knowledge and experience than I have:
The LocalHost computer is Windows (Windows 7).
The DEV and PROD environments are on Linux.
LocalHost, DEV, and PROD all use the same login process: <cfldap>.
We updated at the end of 2014 from ColdFusion 9 to ColdFusion 11 in all environments (including my LocalHost). This issue did not present itself in ColdFusion 9; rather, it started when I updated to ColdFusion 11.
I do not have access to the ColdFusion Administrator on the Linux machines (DEV and PROD), although I do, of course, have access to it on my LocalHost.
Consider enabling/disabling J2EE session variables in ColdFusion Administrator: Server Settings > Memory Variables > Use J2EE session variables.
(In the situation for which I posed the question, the problem was resolved by disabling J2EE session variables.)
Related
I have a Flask site deployed to IIS via wfastcgi configuration.
When I use chrome or firefox developer tools to analyse the loading time of the homepage, I find many seconds (ranging from 6 to 10 in average) as waiting time to receive the first byte.
It was even 30 seconds before, but then I "optimized" my python code to avoid any db sql operation at loading time. Then I've followed the hints of this blog of nspointers, and now from the taskbar of the server I see the w3wp.exe for my app pool identity
w3wp.exe – It is the IIS worker process for the application pool
staying up and running even during idle time. But that is not true for the other
python.exe – The main FastCGI process for the Django or flask
applications.
and I'm not sure if this is a problem and just in case what I am supposed to do, aside from the step 4 described in the mentioned post.
Now in the “Edit FastCGI Application” dialog under “Process Model”
edit the “Idle Timeout” and set it to 2592000 which is the max value
for that field in seconds
I've also looked at the log written by the Flask app and compared it to the log written by IIS and this is the most important point in making me believe that the issue is in the wfastcgi part, before the execution of the python code.
Because I see that the time-taken of the IIS log matches with the client time reported by chrome or firefox as TTFB and the log written by python at the start of the execution is logged at almost the same time of the time written by IIS, that
corresponds to the time that the request finished
(as I thought indeed and as I find it's confirmed by this answer)
So in conclusion, based on what I tried and what I understand, I suspect that IIS is "wasting" many seconds to "prepare" the python wfascgi command, before actually starting to execute my app code to produce a response for the web request. It is really too much in my opinion, since other applications I've developed (for example in F# WebSharper) under IIS without this mechanism of wfastcgi load immediately in the browser and the difference in the response time between them and the python Flask app is quite noticeable. Is there anything else I can do to improve the response time?
Ok, now I have the proof I was searching and I know where the server is actually spending the time.
So I've researched a bit about the wfastcgi and finally opened the script itself under venv\Lib\site-packages.
Skimming over the 900 lines, you can spot the relevant log part:
def log(txt):
"""Logs messages to a log file if WSGI_LOG env var is defined."""
if APPINSIGHT_CLIENT:
try:
APPINSIGHT_CLIENT.track_event(txt)
except:
pass
log_file = os.environ.get('WSGI_LOG')
if log_file:
with open(log_file, 'a+', encoding='utf-8') as f:
txt = txt.replace('\r\n', '\n')
f.write('%s: %s%s' % (datetime.datetime.now(), txt, '' if txt.endswith('\n') else '\n'))
Now, well knowing how to set the environment variables, I defined a specific WSGI_LOG path, and here we go, now I see those 5 seconds TTFB from chrome (as well as the same 5 seconds from IIS log with time 11:23:26 and time-taken 5312) in the wfastcgi.py log.
2021-02-01 12:23:21.452634: wfastcgi.py 3.0.0 initializing
2021-02-01 12:23:26.624620: wfastcgi.py 3.0.0 started
So, of course, wfastcgi.py is the script one would possibly try to optimize...
BTW, after digging into it, that time is due to importing the main flask app
handler = __import__(module_name, fromlist=[name_list[0][0]])
What remains to be verified is the behavior of rerunning the process (and the import of the main flask module, that is time consuming) for each request.
In conclusion, I guess it is a BUG, but I have solved it by deleting the "monitoring changes to file" FastCGI settings as per the screenshot below.
The response time is under a second.
I have a different answer to you by suggesting you try to switch over to HTTP Platform Handler for your IIS fronted Flask app.
Config Reference
This is also the recommended option by Microsoft:
Your app's web.config file instructs the IIS (7+) web server running on Windows about how it should handle Python requests through either HttpPlatform (recommended) or FastCGI.
https://learn.microsoft.com/en-us/visualstudio/python/configure-web-apps-for-iis-windows?view=vs-2019
Example config can be:
<configuration>
<system.webServer>
<handlers>
<add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="c:\inetpub\wwwroot\run.cmd"
arguments="%HTTP_PLATFORM_PORT%"
stdoutLogEnabled="true"
stdoutLogFile="c:\inetput\Logs\logfiles\python_app.log"
processPerApplication="2"
startupTimeLimit="60"
requestTimeout="00:01:05"
forwardWindowsAuthToken="True"
>
<environmentVariables>
<environmentVariable name="FLASK_RUN_PORT" value="%HTTP_PLATFORM_PORT%" />
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>
With run.cmd being something like
cd %~dp0
.venv\scripts\waitress-serve.exe --host=127.0.0.1 --port=%1 myapp:wsgifunc
Note that the HTTP Platform handler will dynamically set on a port and passing that into the python process via the FLASK_RUN_PORT env var which flask will automatically take as a port configuration.
Security notes:
Make sure you bind your flask app to localhost only, so it's not visible directly from the outside - especially if you are using authentication via IIS
In the above example the forwardWindowsAuthToken is being set which then can be used to rely on Windows Integrated authentication done by IIS then the token passed over to Python and you can get the authenticated user name from Python. I have documented that here. I actually use that for single-sign on with Kerberos and AD group based authorization, so it works really nice.
Example to only listen on localhost / loopback adapter to avoid external requests hitting the python app directly. In case you want all requests to go via IIS.
if __name__ == "__main__":
app.run(host=127.0.0.1)
We have a strange situation. It's a web service (svc1) that calls another web service (svc2) on a different box, both in websphere. Works in every previous environment.
But recently they built out another staging environment as largely a clone of a working one. The service is failing with this message everytime svc1 attempts to call svc2.
Caused by: org.apache.axis2.AxisFault: The system cannot infer the transport information from the [svc2's URL] URL.
at org.apache.axis2.description.ClientUtils.inferOutTransport(ClientUtils.java:81)
at org.apache.axis2.client.OperationClient.prepareMessageContext(OperationClient.java:304)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:180)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:578)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.doInvoke(AxisInvocationController.java:127)
at org.apache.axis2.jaxws.core.controller.impl.InvocationControllerImpl.invoke(InvocationControllerImpl.java:93)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:419)
... 45 more
The URL is correct. We can point the not-working apps at a database supporting a working set of apps and it works, but when we point the working apps from that other environment at the not-working environment's DB, it stops working.
This seems to indict the DB, yet the error has nothing to do with the DB. Svc1's only DB call BEFORE the call to svc2 happens well before the service call and works fine according to logs. The logs indicate svc2 never gets the request. So how can database be the problem?
I know this isn't alot to go on, but does anyone even have suggestions on where to look to narrow this down? I can't believe the DB is the problem based on the code and when it's failing...yet the DB swapping test seems to imply it is.
I might be pointing out the obvious, but the error message is telling you one of two things: either svc1 isn't configured correctly to invoke svc2, or svc2 isn't up and running.
For clarity, if I label the working environment: enviornmentA and the not-working environment: environmentB.
Based on what you said, you were able to use environmentB.svc1 to invoke environmentA.svc2? If that is true, than environmentB.svc1 is configured correctly and working. Which leaves svc2. You said svc2 doesn't receive the request, which means its up at least. Well, like you'd mention this isn't much to go on but I'd make sure you configured svc2 correctly, since it is up. Configuring a Web Service can be complicated, but one of the things that can be configured is making a Web Service available to client invocation. So you might want to check out this link for information on how to configure it:
https://www.ibm.com/support/knowledgecenter/SSAW57_9.0.0/com.ibm.websphere.nd.multiplatform.doc/ae/twbs_publishwsdl.html.
There are a bunch of similar articles on configuring your Web Service that might help you to solve what's missing, so I would verify that the configuration for enviornmentB.svc2 matches enviornmentA.svc2 since you know that one is working.
I have 2 asp .net applications running on the same domain (both in staging & production). Application A opens a page from Application B in a popup window. The cookie names for staging and production are different.
But strangely for some users, even though the request is for production, staging cookies are being appended to the request. Is it a cached request being pulled from somewhere? Where the production cookies going? In Application A the cookies are found and they are fine. But Application B is getting the staging/wrong cookies.
Sorry for not sharing any code for confidentiality issues. Here's an example:
In application A, following cookies are there:
BDT, path="/", domain=".sample.com" (this is production)
In application B, cookies are somewhat like this:
SBDT, path="/", domain=".sample.com" (this is staging cookie)
Is the request being cached (at the machine or some proxy server) and being issued repeatedly? Or can it be some mal-ware/virus?
User is using IE9 (in IE7 mode) on Windows 7
finally we cracked it.
We again carefully analyzed the HttpWatch logs and noticed that, the App B is being run in IE protected mode, where as App A is not.
We requested the client to clear the cache and launch the applications again. After that we found that,
App B is getting NO cookies at all
We made a guess that, they are running in IE protected mode with High security level enabled. And they have ONLY 'App A' in the trusted sites list i.e AppA.sample.com
We requested them to add *.sample.com instead and that FIXED the issue.
For more details check:
Persistent cookies are not shared between Internet Explorer and Office applications
I am trying to set my cookie CFIDE and CFTOKEN to be HTTPOnly in Coldfusion 9...
Here is what I have tried (didn't error but didn't work):
cookie.CFID = "#session.cfid#,httpOnly='true'";
cookie.CFTOKEN = "#session.cftoken#,httpOnly='true'";
I also tried (no go...and no error):
cookie.CFID = "#session.cfid#;httpOnly='true'";
cookie.CFTOKEN = "#session.cftoken#;httpOnly='true'";
And this (which I think only works in CF10):
cookie.CFID = {value="#session.cfid#", httpOnly="true"};
cookie.CFTOKEN = {value="#session.cftoken#", httpOnly="true"};
Then this (didn't error but didn't work):
cookie( name="CFID" value="#session.cfid#" httpOnly="true" );
cookie( name="CFTOKEN" value="#session.cftoken#" httpOnly="true" );
When I run these I do a empty cache hard reload in Chrome. When the page reloads I should see the Resources Cookies HTTPOnly column show check boxes.
I'm probably exhausted and could have hit the right combo of things above and I got a false positive on failure from jumping around too much. Sometimes cached things get the best of me.
I have the CFML container style that works but my Application.cfc is all script style and I want to keep it that way...So how do I do this script style in Coldfusion 9?
Update for my fix:
I used the getPageContex() below, but it didn't work as it was. Also onSessionStart() event handler changed to create the session.CFID and session.CFTOKEN with the CreateUUID() which is also new in my Application.cfc file. So for posterity here is what that block of code looks like.
function onSessionStart(){
getPageContext().getResponse().addHeader("Set-Cookie", "CFID=#session.CFID#;path=/;HTTPOnly");
getPageContext().getResponse().addHeader("Set-Cookie", "CFTOKEN=#session.CFTOKEN#;path=/;HTTPOnly");
}
Another Note: For some reason if the session is cleared and the onsessionstart() handler is requested this set cookie stuff above will fail. There has to be a try catch block or exception handling of some sort added to account for a reload problem. The best thing is to upgrade to a patched up release of Coldfusion 10 (or soon to be released CF 11).
You can use the PageContext object to set cookies in cfscript:
getPageContext().getResponse().addHeader("Set-Cookie", "CFID=#session.CFID#;path=/;HTTPOnly");
getPageContext().getResponse().addHeader("Set-Cookie", "CFTOKEN=#session.CFTOKEN#;path=/;HTTPOnly");
For session cookies, there's an easier way.
Enabling server-wide HttpOnly session cookies
The ColdFusion 9.0.1 update added a server-wide setting to add the
httponly attribute to all session cookies created by ColdFusion (such
as the CFID and CFTOKEN cookies, or the JSESSIONID cookie on JRun). To
enable this setting, if you are running a JRun J2EE installation or
multi-server installation, you must edit jvm.config, otherwise you can
enable this setting from the CF Administrator. If you are running a
J2EE server other than JRun consult your documentation for an
appropriate setting. J2EE servers that support the Servlet 3.0
specification can specify
true
in the /WEB-INF/web.xml file.
http://www.adobe.com/devnet/coldfusion/articles/coldfusion-securing-apps.html
You can use this code in your application.cfc inside of the onsessionstart function.
<cfcookie name="CFID" value="#session.cfid#" httponly="true">
<cfcookie name="CFTOKEN" value="#session.cftoken#" httponly="true">
There is no way of setting this inside of cfscripts. cfcookie is not supported in script form in cf9. There are flags in the application settings added to CF10 to address this issue, however, CF11 will have full support for it inside of scripts. Unfortunately, I think you will have to forego the uniform code for functionality. Unless you have access to your CFIDE/Administrator. You can add a java argument to turn it on server wide. Add this to your JVM config
-Dcoldfusion.sessioncookie.httponly=true
All of this is detailed here http://www.petefreitag.com/item/764.cfm
Okay, this is really kinda starting to bug me. I have a simple Web project setup located at: "C:\Projects\MyTestProject\". In IIS on my machine, I have mapped a virtual directory to this location so I can run my sites locally (I understand I can run it from Visual Studio, I like this method better). I have named this virtual directory "mtp" and I access it via http://localhost/mtp/index.aspx. All this is working fine.
However, whenever I try to create a cookie, it simply never gets written out? I've tried this in FF3 and IE7 and it just plain won't write the cookie out. I don't get it. I do have "127.0.0.1 localhost" in my hosts file, I can't really think of anything else I can do. Thanks for any advice.
James
The cookie specs require two names and a dot between, so your cookiedomain cannot be "localhost". Here's how I solved it:
Add this to your %WINDIR%\System32\drivers\etc\hosts file:
127.0.0.1 dev.livesite.com
When developing you use http://dev.livesite.com instead of http://localhost
Use ".livesite.com" as cookiedomain (with a dot in the beginning) when creating the cookie.
Modern browsers doesn't require a leading dot anymore, but you may want to use anyway for backwards compability.
Now it works on all sites:
http://dev.livesite.com
http://www.livesite.com
http://livesite.com
Since an answer has never been chosen, I suppose I can still throw something else out there.
One reason you can run into no cookies being written with an application running under localhost is the httpCookies setting in the web.config. If the domain attribute was set to a specific domain and you run under localhost, the cookies did not get written for me.
Remove the domain attribute in development and the cookies are written:
<!-- Development -->
<httpCookies httpOnlyCookies="true" requireSSL="false" />
<!-- Production -->
<!--<httpCookies domain=".domain.com" httpOnlyCookies="true" requireSSL="true" />-->
Are you assigning an expiration date to the cookie? By default, the cookie will expire when the browser session expires, meaning it won't write anything to disk.