Dynamic Subdomains - ColdFusion 11 - coldfusion

Anyone know a way to create dynamic subdomains in coldfusion 11 without having to add them to a dns server?
I want to be able to redirect each of my clients in a personalized subdomain every time they log in to my system.
ex: client1.example.com client2.example.com

This works if your site is hosted in a Windows IIS server.
If you are using IIS then the following can help you. Use loops and conditions as your requirements.
<!--- Provide you IIS SiteName --->
<cfset siteName = "Your IIS Site Name">
<!--- Your new domain address --->
<cfset newSiteBinding = "client2.example.com">
<!--- your port address --->
<cfset newSitePort = 80>
<cfset fileID = createUUID()>
<cfsavecontent variable="ex"><cfoutput>cd %windir%\system32\inetsrv
%windir%\system32\inetsrv\APPCMD set site /site.name: #siteName# /+bindings.[protocol='http',bindingInformation='*:#newSitePort#:#newSiteBinding#']</cfoutput>
</cfsavecontent>
<cffile action = "write"
file = "E:\#fileID#.bat"
output = "#ex#"
/>
<cfexecute name="E:\#fileID#.bat"
arguments="/c set"
variable="data"
timeout="10"
/>
<cffile action = "delete"
file = "E:\#fileID#.bat"
>
What we are basically doing is that we are creating a .bat file and executing it using cfexecute. Please note that you need to be careful with the paths because the Directory structure might be different in your server.
.BAT file content Example
cd %windir%\system32\inetsrv
%windir%\system32\inetsrv\APPCMD set site /site.name: example /+bindings.[protocol='http',bindingInformation='client2.example.com:80:*']
How the command works. Notice the + at /+bindings?
That means adding a new binding and /-bindings tries to remove an existing binding.

Related

Coldfusion 2021 loads white pages for cfm files

Here's some small info about the server:
Windows Server 2019
Coldfusion 2021
IIS 10
<!--- Dump out the server scope. --->
<cfdump var="#SERVER#" />
<!--- Store the ColdFusion version. --->
<cfset strVersion = SERVER.ColdFusion.ProductVersion />
<!--- Store the ColdFusion level. --->
<cfset strLevel = SERVER.ColdFusion.ProductLevel />
I've added everything in IIS, CGI, ISAPI Filters and Restrictions and I have all the handlers. I do have .cfm in the default documents. Issue I keep seeing on my test page is just a blank white screen. This was my test file coding:
What might be the issue and why am I just getting a white screen of death on all my cfm pages?
Thanks
Sounds like a disconnect between the app engine and IIS. You should look into commandbox: https://commandbox.ortusbooks.com/setup/installation
Also has BonCode connectors for IIS. https://commandbox.ortusbooks.com/embedded-server/external-web-server

URL Rewrite with IIS using ColdFusion

I've done a bit of searching but just can't put it all together. Here's what I need:
I'd like someone to surf to:
www.mysite.com/thisPlace
and have it redirect them to
www.mysite.com/template.cfm?pm=ms&loc_id=4
To do so, I somehow need to capture that they didn't request an existing file in their http request and run a .cfm page that queried the database for a record where locationName = 'thisPlace' and then redirect them to a page like
template.cfm?pm=ms&loc_id=4, where 4 is the record id of the row that matched 'thisPlace'
If your default document in IIS is set to index.cfm you could create a folder (directory) called "thisPlace" and place an index.cfm file that contains nothing but a <cflocation> tag and the accompanying query/logic to figure the URL.
Website.com/thisPlace would then function as you describe.
Edit:
You could add a custom 404 page...
Make it a .cfm file instead of html. Scan the template path to see what the user is looking for. If you find it in your database, redirect them there, else redirect them to a general 404 page.
<!---Up to a certain point (the directory in which you store your code) this will always be the same so you can hard-code your number --->
<cfset QueryConstant = #LEFT(CGI.CF_Template_Path, 22)#>
<!---Find the overall length of the template path. --->
<cfset QueryVariable = #Len(CGI.CF_Template_Path)#>
<!---Take whatever is past your QueryConstant (AKA the string that produces a 404 error.) --->
<cfset theRightNumber = QueryVariable - 22>
<cfset QuerySearchString = #RIGHT(CGI.CF_Template_Path, theRightNumber)#>
<cfquery name="ListOfLocations" datasource="CRM">
SELECT TOP 1 LocationID
FROM LocationTable
WHERE LocationName LIKE '%#QuerySearchString#%'
</cfquery>
<cfif ListOfLocations.recordcount>
<cflocation url="/SomePage.cfm?LocationID=#ListOfLocations.LocationID#">
<cfelse>
<cflocation url="/Regular404page.html">
</cfif>
Thanks guys! Huge help! Using your inputs, here's what I did:
(had to use QUERY_STRING instead of CF_Template_Path, as CF_Template_Path did not pass along anything after the url of the custom error page.
I set up a custom 404 error Execute URL in IIS to a file named check404error.cfm.
When someone looks for www.example.com/thisPlace, IIS sends them to http://www.example.com/check404error.cfm. I use the CGI.QUERY_STRING (404;http://www.example.com:443/thisPlace) to ultimately get the "thisPlace" string to search with.
<!---Up to a certain point (the directory in which you store your code) this will always be the same so you can hard-code your number --->
<cfset QueryConstant = #LEFT(CGI.QUERY_STRING, 31)#>
<!---Find the overall length of the template path. --->
<!---31 is the length of '404;http://www.example.com:443/' --->
<cfset QueryVariable = #Len(CGI.QUERY_STRING)#>
<!---Take whatever is past your QueryConstant (AKA the string that produces a 404 error.) --->
<cfset theRightNumber = QueryVariable - 31>
<cfset QuerySearchString = #RIGHT(CGI.QUERY_STRING, theRightNumber)#>
<cfquery name="ListOfLocations" datasource="#request.dsn#">
SELECT location.id
FROM location WHERE url_name = <cfqueryparam value="#QuerySearchString#" cfsqltype="CF_SQL_VARCHAR" maxlength="255"> LIMIT 1
</cfquery>
<cfif ListOfLocations.recordcount>
<cflocation url="https://example.com/template.cfm?pm=ms&loc_id=#ListOfLocations.id#" addtoken="no" statusCode="301">
<cfelse>
<cflocation url="/404error.cfm" addtoken="no">
</cfif>
This is how most popular MVC Framework work today, by parsing out the URL segments.
Do you have access to any kind of URL rewrite software?
Since you are using IIS it has a built in rewrite engine where you could simply rewrite these kind of requests to a known file saving you the overhead of sending a 404 reply and parsing that out and having more request created as a result of that.
See http://wiki.coldbox.org/wiki/URLMappings.cfm for details. We use the Isapi rewrite version version to do just what you are asking for
Receive request for www.mysite.com/thisPlace
thisPlace isn't a directory
thisPlace isn't a file
Resend to index.cfm or a location of your chosing for additional parsing
Helicon Rewrite sends an HTTP header named HTTP_X_REWRITE_URL with the original requested URL so parsing it out is then very easy.
This all happens inline withing the one request so the client is never redirected.

Using <cfinclude> with this.mapping

In my application I have a header and footer include. In my Application.cfc I've set up a function that names my application and sets mapping.
<cfcomponent output="no">
<cfset this.name = "thesitename">
<cfset this.datasource = "thesitedatasource">
<cfset this.rootDir = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings = structNew()>
<cfset this.mappings["/planning"] = "#this.rootDir#planning/" />
<cfset this.mappings["/images"] = "#this.rootDir#images/" />
<cfset this.mappings["/includes"] = "#this.rootDir#includes/" />
<cfset this.mappings["/js"] = "#this.rootDir#js/" />
<cfset this.mappings["/portfolio"] = "#this.rootDir#portfolio/" />
</cfcomponent>
If I have a page in a subdirectory like this: planning/index.cfm the <cfinclude> can't locate anything in the images folder when I use the following path: <li class="imagelink"><img src="/images/facebook.png"></li>
Pages in the root directory don't have a problem.
If I understand correctly, the problem has to do with the mapping doesn't take place prior to the include being called, or something like that... How do I get the mapped paths to work properly in my include?
ColdFusion mappings are completely separate from a web server 'alias' or 'virtual directory'. In order for your code to work, you will need to add a web server mapping, 'alias' in Apache or 'virtual directory' in IIS, named 'images' that points to the directory where you keep the images.
The 'images' ColdFusion mapping will only work in ColdFusion - for example, when creating an object, you could use createObject( "component", "images.image") (assuming of course that you had a CFC named Image in that diectory.

Is a CFLogin replacement necessary or am I missing something?

I'm seriously considering moving away from CF8 cflogin because it is tied to the server that spawned the login. In a load balanced environment you're stuck with sticky sessions if you don't do a custom implementation.
Does anyone have any source that mimics CFLogin that writes to and is managed from the client scope? Maybe even a design that matches up well with a rename replace on isuserin[any]role.
What should I be thinking about when I consider writing a replacement implementation for CFLogin?
Here is a basic non cflogin approach using variables stored in the CLIENT scope. We use a similar approach for non-sticky sessions across our server cluster behind our load balancer.
This code should live in Application.cfc -> onRequestStart() method:
<!--- handle login *post* --->
<cfif structKeyExists(FORM, "pageaction") and FORM.pageAction eq "adminlogin">
<!--- attempt to log user in --->
<cfif loginSuccessful>
<!--- Set client variables for session management --->
<cfset CLIENT.lastHit = now() />
<cfset CLIENT.loggedIn = 1 />
<!--- redirect to home page --->
<cfelse>
<!--- redirect to login page with message --->
</cfif>
<!--- all other requests, except for the login page --->
<cfelseif structKeyExists(CLIENT, "lasthit") and structKeyExists(COOKIE, "cfid") and structKeyExists(CLIENT, "cfid") and listLast(CGI.SCRIPT_NAME, "/") neq "login.cfm">
<!--- Check for timeout --->
<cfif (datediff("n", CLIENT.lastHit, now()) lte 10) and (CLIENT.loggedIn is 1) and (CLIENT.cfid is COOKIE.cfid)>
<!--- record last hit --->
<cfset CLIENT.lastHit = now() />
<cfelse>
<!--- timeout! redirect to login page --->
<cflocation URL="http://mydomain/login.cfm" addtoken="false" />
</cfif>
</cfif>
There is user role stuff, but I hope this helps as a starting point.
I customized the CF Login Wizard through Dreamweaver to be portable and to use a db table for authentication and role management. Because of this,I can use it either as a single-user login, or multiple account logins. I never have used cflogin and haven't needed to. I just drop the files into the directory, customize the login credentials, and that is it. Works perfect every time.

How can I tell if a user belongs to an role in active directory - using ColdFusion

If I am using integration authentication in IIS, how can I determine if the current user is part of a specific active directory role, using ColdFusion.
This would be analogous to using the IsInRole() method of the User object in .net - how can it be done in ColdFusion
the only way to do this is to use cflap and query the active directory server to get a list of groups. after you've gotten the list, you will need to parse it to see if that user belongs to the group in question. below is some code i wrote with some comments for the people at work. values have been changed to protect the innocent.
<!--- getting the user login id --->
<cfset variables.thisuser = ListLast(cgi.AUTH_USER, "\")>
<!--- this is the group they must be a memberof --->
<cfset variables.groupname = "CN=<the group to search for>">
<!--- list of all groups that the user belongs to, will be populated later --->
<cfset variables.grouplist = "">
<cftry>
<cfldap action="query"
name="myldap"
attributes="memberOf"
start="OU=<your ou>,DC=<your dc>,DC=<your dc>"
scope="subtree"
filter="(sAMAccountName=#variables.thisuser#)"
server="<your AD server ip>"
port="<your AD server port>"
username="<network login if required>"
password="<network password if required>">
<cfset variables.grouplist = myldap.memberOf>
<cfcatch>
</cfcatch>
</cftry>
<cfif FindNoCase(variables.groupname, variables.grouplist)>
<cfcookie name="SecurityCookieName" value="">
</cfif>
In coldfusion to check a users role you would use IsUserInRole()
http://cfquickdocs.com/#IsUserInRole
Edit - And actually I hope I understood correctly, I don't know anything about IIS or active directory. As I understood the question you wanted to check a users role in Coldfusion.
I think you may be looking for something more like this: http://vincentcollins.wordpress.com/2008/08/20/active-directory-ldap-authentication/ or this: http://coldfusion.sys-con.com/node/154225
Just as a follow up, SQL server has ADSI providers that allow you to create a linked server to your LDAP servers.
From there you can do ldap queries to your AD and it returns like any other record set.
I find it a little easier to do complex ldap query then via CF.