And likewise for individual sections. Yes, if they only have read permissions, simply put a wrapper around elements which would allow them to submit.
On Wed, Jan 12, 2011 at 11:10 AM, Jason King <[email protected]> wrote: > Why not just wrap the entire page or content section in an IF/THEN that > queries the member permissions if they can view it or not? If pass, then > view, if not, then "permission denied"? > > That's how I'm doing my app. > > > > On Wed, Jan 12, 2011 at 11:08 AM, Skellington <[email protected]> wrote: > >> Denny, >> Wow, a lot more than I thought I would get, thanks. >> >> So a little more background. I'm trying to retrofit my current app to >> add some sort or Role Based access to different sections of the site. >> Right now I'm using Application.cfm and SessionManagment with a form >> based login that does a cfldap query to our active directory >> environment to validate the user logging in. While all of this works >> very well the data in the app/site is all ready only, for the most >> part. I guess my real question is, is it common to just use if >> statements to filter access to a page? For example if a user has read >> only to a page with a form, do I wrap the submit button in a if >> statement and check to see if they have edit access, if so allow them >> to submit? >> >> Sorry, if this response seems like I'm rambling :-) I have had my >> coffee yet. >> >> >> Thanks, >> Charlie >> >> >> >> On Jan 12, 6:06 am, Denard Springle <[email protected]> wrote: >> > Hey Charlie, >> > >> > There are a number of ways to implement access controls in CFML >> > depending on your needs. I'm not clear what the scope of your project >> > is or what you're trying to accomplish but I can offer some >> > assistance... >> > >> > You're going to need a few basic pieces to implement >> > authentication, session management and access control. Assuming you >> > haven't done the authentication piece yet, you'll need the following: >> > >> > 1. A sign-up form and/or admin form for adding users to a user >> > database table so they can later authenticate against the stored >> > information. >> > 1a. A password reset and change password form and functions are also >> > recommended. >> > 1b. System generated random passwords for initial sign-up/adding of >> > users and password resets is strongly recommended. >> > >> > 2. A FORM that gathers the username and password of the user and >> > submit to a processor page (can be the same page) >> > >> > 3. A user database table to store the login information for your >> > clients, something along the lines of: >> > >> > id int auto-increment >> > username varchar(255) not null >> > password varchar(255) not null >> > last_on datetime >> > >> > 3a. NOTE: Use Hash() on your passwords and encrypt passwords and >> > usernames before storing them in the database. Use a javascript Hash() >> > routine on your login form to hash your users passwords before they >> > are sent to the browser. >> > 4. A processor that looks for the (encrypted) username and (hashed and >> > encrypted) password submitted by the user from the user database table >> > 4a. If there is a match, then you kick into session management and >> > access controls >> > >> > 5. Session Management can be handled by the combination of either >> > SESSION scoped variables (be sure to <cflock> them when you set them >> > to prevent race conditions) or a COOKIE and another database table to >> > manage sessions, something along the lines of: >> > >> > id int auto-increment >> > session_id varchar(255) not null >> > user_id varchar(255) not null >> > last_action datetime not null >> > >> > 5a. NOTE: Generate a session id with CreateUUID() or another random >> > pattern generator, encrypt the session id and user id before storing >> > in the database. >> > 5b. Encrypt your encrypted session id (pref using a diff algorithm) >> > and then use that value as either your SESSION scoped variable value >> > or your COOKIE value >> > >> > 6. Application.cfc session management is suggested. This is done by >> > having an OnRequestStart block that, if within a specific path >> > (CGI.PATH_INFO) of the site usually, reads in the SESSION scoped >> > variable or COOKIE on each request, compares the time of the last >> > request to some timeout period you've set as an APPLICATION variable >> > in the Application.cfc and the current time (e.g. if 15 minutes have >> > passed since the last user action on the site, for example) and then >> > either refreshes the session by updating the last_action field in the >> > session database table (if 15 minutes have not passed) or return them >> > to the login page (if 15 minutes have passed) with a 'session timeout' >> > message, and if you're crafty about it, the ability to return the user >> > to the page he was visiting before the session times out. >> > >> > 7. Access Control is a means of limiting already authenticated users >> > to specific areas or specific content on your website. For example, an >> > average CMS site might have authors, content reviewers and moderators >> > each representing different abilities and access to different parts of >> > the average CMS backend. Authors would be able to write and modify >> > articles, content reviewers would be able to write, modify and publish >> > articles and moderators may simply only be able to approve content for >> > publishing, for examples. This type of access control can be >> > implemented in one of two standard ways, as follows: >> > >> > 7a. Roles - you can either add another table to your database to >> > manage the role/user relationship, or you can use a list based >> > approach with a single field added to your users table called roles, >> > either one works and simply depends on preference and code required. >> > In both cases, you have to either have another table the represents >> > the relationship between pages or content on your site and the allowed >> > Roles able to access them - which is handled in a similar way to >> > handling user roles - either as a relationship table (page/role) or as >> > a list of allowed roles referencing one page (page/roles), or can be >> > hard coded into each page you wish to check (e.g. <cfif >> > Find(qGetUser.Roles,'Author')> ... allowed access content </cfif>). >> > >> > 7b. In the event that you wish to assign multiple roles to the same >> > user, there is a mathematical way to handle this which is much quicker >> > than textual Roles and allows for a much smaller footprint in your >> > database. It is, however, slightly more complicated and complex. The >> > easiest way to explain it is with a bit of code I wrote to illustrate >> > that capabilities of using positional math with a single 32-bit byte >> > to assign (up to) 32 roles to a single user with one byte. 64-bit >> > systems running 64-bit CF can also handle 64-bit bytes quickly (32-bit >> > CF can also do 64-bit positional math, but it requires two processor >> > cycles), allowing for up to 64 roles to a single user in a single >> > byte. >> > >> > <!--- >> > Name: using_bit_based_access_control.cfm >> > Author: Denard Springle ( [email protected] ) >> > Description: Demonstrate using binary objects and bit manipulation >> > Created: 05/06/2009 >> > License: Creative Commons Attribution-Non Commercial 3.0 >> > ---> >> > <!--- initialize a string to hold the binary representation of our 32- >> > bit zero byte ---> >> > <cfset zeroByte = ""> >> > <!--- initialize the zero byte ---> >> > <cfset zeroByte = RepeatString('0',32)> >> > <!--- set up a row color variable to alternate colors ---> >> > <cfset rC = 0> >> > <!--- set up a table to output the progress and results of this >> > operation ---> >> > <h1>32 Bit Combinations</h1> >> > <p>The following table represents the 32 bit positions available in a >> > 32-bit byte. By using these positions you can assign up to 32 access >> > control levels to the same user without depending on role lists (i.e. >> > IsUserInRole() style). Storage and processing of a single 32-bit byte >> > is demonstrated here in it's most basic form for easy digestion, >> > however the use of single 32-bit byte is an optimal mathmatic >> > calculation and storage method for tiered access controls.</p> >> > <table cellpadding="2" cellspacing="0" width="50%"> >> > <tr> >> > <th style="text-align:center;">Bit Pos</th> >> > <th style="text-align:center;">Bin Val</th> >> > <th style="text-align:center;">Dec Val</th> >> > <th style="text-align:center;">Hex Val</th> >> > </tr> >> > <!--- set up the first row (of zero's) ---> >> > <tr style="background-color:#FFFFEE;"> >> > <td style="text-align:center;">0</td> >> > <td style="text-align:center;">[ >> > <cfoutput>#zeroByte#</cfoutput> >> > ]</td> >> > <td style="text-align:center;">0</td> >> > <td style="text-align:center;">0</td> >> > </tr> >> > <!--- create a new structure to hold the access controls ---> >> > <cfset thisStruct = StructNew()> >> > <!--- put the zero byte in the structure (for later use) ---> >> > <cfset structInsert(thisStruct, 'this0', zeroByte)> >> > <!--- loop through the 31 assignable bits (e.g. excluding zero [0]) --- >> > >> > <cfloop from="1" to="31" index="iX"> >> > <!--- initialize a string to hold the binary representation of our 32- >> > bit byte ---> >> > <cfset binaryByte = ""> >> > <!--- set the current column to 32 bits minus the current index of iX, >> > so, bit 31, 30, 29, etc. ---> >> > <cfset thisCol = 32-iX> >> > <!--- loop through the zero bits which make up the beginning (left) of >> > this byte (e.g. thisCol value) ---> >> > <cfloop from="1" to="#thisCol#" index="iY"> >> > <!--- add this bit positions false (0) bit to the byte string ---> >> > <cfset binaryByte = binaryByte & '0'> >> > <!--- loop through the remaining begininng (left) bit positions that >> > are zero ---> >> > </cfloop> >> > <!--- add this bit positions true (1) bit ---> >> > <cfset binaryByte = binaryByte & '1'> >> > <!--- init remaining columns ---> >> > <cfset newCol = 32-(thisCol+1)> >> > <!--- check if we're at the last element in the list ---> >> > <cfif newCol GT 0> >> > <!--- loop through and pad the right with zero (0) ---> >> > <cfloop from="1" to="#newCol#" index="iZ"> >> > <!--- add a zero (1) to the binary string ---> >> > <cfset binaryByte = binaryByte & '0'> >> > <!--- loop through the rest of the padded zero's ---> >> > </cfloop> >> > <!--- end checking if we're at the last element ---> >> > </cfif> >> > <!--- put this byte in the structure (for later use) ---> >> > <cfset structInsert(thisStruct, 'this#iX#', binaryByte)> >> > <cfif rC EQ 0> >> > <cfset rowCol = "##DDDDEE"> >> > <cfset rC = 1> >> > <cfelse> >> > <cfset rowCol = "##FFFFEE"> >> > <cfset rC = 0> >> > </cfif> >> > <!--- output the current bit position and byte values to the screen --- >> > >> > <cfoutput> >> > <tr style="background-color:#rowCol#;"> >> > <td style="text-align:center;">#iX#</td> >> > <td style="text-align:center;">[#binaryByte#]</td> >> > <td style="text-align:center;">#InputBaseN(binaryByte,2)#</td> >> > <td style="text-align:center;">#FormatBaseN(InputBaseN(binaryByte,2), >> > 16)#</td> >> > </tr> >> > </cfoutput> >> > <!--- loop through the rest of the possible byte values ---> >> > </cfloop> >> > <!--- end the table ---> >> > </table> >> > <br> >> > <br> >> > <!--- dump the structure ---> >> > <h1>The structure</h1> >> > <cfdump var="#thisStruct#"> >> > <br> >> > <br> >> > <h1>The Test Case</h1> >> > <p>In this test case we are going to add existing members of the >> > structure (bytes) together. By adding these bytes together and then >> > converting back to base 2 (binary) output you will see how multiple >> > levels could be assigned to the same user.</p> >> > <!--- create a test case by adding together random bits from the 31 >> > bytes created and stored in the structure ---> >> > <cfset testCase = InputBaseN(structFind(thisStruct, 'this11'),2) + >> > InputBaseN(structFind(thisStruct, 'this16'),2) + >> > InputBaseN(structFind(thisStruct, 'this19'),2) + >> > InputBaseN(structFind(thisStruct, 'this2'),2)> >> > <!--- initialize an output string ---> >> > <cfset testCaseOutput = ""> >> > <!--- loop through the missing begining (left) zero bit's ---> >> > <cfloop from="1" to="#32-Len(FormatBaseN(testCase,2))#" index="iX"> >> > <!--- add the missing zero bits ---> >> > <cfset testCaseOutput = testCaseOutput & '0'> >> > <!--- loop through the rest of the zero bit's ---> >> > </cfloop> >> > <!--- set the output string to the zero's concantenated with the >> > binary output of the test case ---> >> > <cfset testCaseOutput = testCaseOutput & FormatBaseN(testCase,2)> >> > <!--- initalize a role list to capture the role names ---> >> > <cfset roleList = ""> >> > <table cellpadding="2" cellspacing="0"> >> > <tr> >> > <th style="text-align:center;">Test Case Binary</th> >> > <th style="text-align:center;">Test Case Decimal</th> >> > <th style="text-align:center;">Current Bit Binary</th> >> > <th style="text-align:center;">Current Bit Decimal</th> >> > <th style="text-align:center;">Result</th> >> > </tr> >> > <tr style="background-color:#FFDDDD;"> >> > <td style="text-align:center;">[ >> > <cfoutput>#testCaseOutput#</cfoutput> >> > ]</td> >> > <td style="text-align:center;"><cfoutput>#testCase#</cfoutput></td> >> > <td style="text-align:center;">[ >> > <cfoutput>#structFind(thisStruct, 'this0')#</cfoutput> >> > ]</td> >> > <td style="text- >> > align:center;"><cfoutput>#InputBaseN(structFind(thisStruct, 'this0'), >> > 2)#</cfoutput></td> >> > <td style="text-align:center;">False</td> >> > </tr> >> > <!--- loop through the 31 bytes in the structure ---> >> > <cfloop from="1" to="31" index="iX"> >> > <!--- output the current test byte itteration (iX) information ---> >> > <cfoutput> >> > <!--- perform BitAnd against the current byte (iX) and the testCase >> > byte ---> >> > <cfif BitAnd(InputBaseN(structFind(thisStruct, 'this#iX#'), >> > 2),testCase)> >> > <!--- if BitAnd returns true, then the bit represented by the current >> > byte (iX) is present in the testCase byte ---> >> > <tr style="background-color:##BBFFBB;"> >> > <td style="text-align:center; border-left:1px solid ##000000; border- >> > top:1px solid ##000000; border-bottom:1px solid >> > ##000000;">[#testCaseOutput#]</td> >> > <td style="text-align:center; border-top:1px solid ##000000; border- >> > bottom:1px solid ##000000;">#testCase#</td> >> > <td style="text-align:center; border-top:1px solid ##000000; border- >> > bottom:1px solid ##000000;">[#structFind(thisStruct, 'this#iX#')#]</ >> > td> >> > <td style="text-align:center; border-top:1px solid ##000000; border- >> > bottom:1px solid ##000000;">#InputBaseN(structFind(thisStruct, >> > 'this#iX#'),2)#</td> >> > <td style="text-align:center; border-top:1px solid ##000000; border- >> > bottom:1px solid ##000000; border-right:1px solid ##000000;">True</td> >> > </tr> >> > <!--- set the value of this byte in the role list ---> >> > <cfset roleList = ListAppend(roleList,structFind(thisStruct, >> > 'this#iX#'))> >> > <!--- otherwise, BitAnd returned false, so the bit represented by the >> > current byte (iX) is *not* present in the testCase byte ---> >> > <cfelse> >> > <tr style="background-color:##FFDDDD;"> >> > <td style="text-align:center;">[#testCaseOutput#]</td> >> > <td style="text-align:center;">#testCase#</td> >> > <td style="text-align:center;">[#structFind(thisStruct, 'this#iX#')#]</ >> > td> >> > <td style="text-align:center;">#InputBaseN(structFind(thisStruct, >> > 'this#iX#'),2)#</td> >> > <td style="text-align:center;">False</td> >> > </tr> >> > </cfif> >> > <!--- end checking current test byte ---> >> > </cfoutput> >> > <!--- loop through to the next byte ---> >> > </cfloop> >> > </table> >> > <br> >> > <br> >> > <h1>The result</h1> >> > <p>Listed below are the binary roles detected by the BitAnd checking >> > routine.</p> >> > <!--- output the roles randomly picked ---> >> > <cfoutput>#roleList#</cfoutput> >> > >> > This is all, of course, subjective and there are a number of different >> > ways to handle authentication, session management and access control >> > in ColdFusion - this is one way. I never use the <cflogin> functions >> > myself so I'm not sure if they're even supported in OpenBD, but if it >> > is then that is another option for the authentication and session >> > management - access control is still up to one of the two methods I >> > suggested, though IsUserInRole() lends itself to the non-bit based, >> > textual approach which I find to be utterly and painfully slow so I >> > almost always use positional math based access controls for speed. But >> > then almost every application I write is chock full of encryption and >> > decryption so every millisecond I can squeeze out of my apps the >> > better ;) >> > >> > Anyway, I hope this answers your question, and if not, just shoot some >> > more specific feedback on what you're trying to accomplish and I'll >> > see if I can't help more ;) >> > >> > -- Denny >> > >> > On Jan 11, 4:21 pm, Skellington <[email protected]> wrote:> Hello, >> > > I'm working on a new application and I dont want to re-invent the >> > > wheel here. I would like to do access control in my application but >> > > I'm not sure how to handle this? Meaning, do I just create a group in >> > > a database table and add users to and then use "if" statements to do >> > > filtering or is there a cfc or plugin that helps with something like >> > > this? >> > >> > > Thanks, >> > > Charlie >> >> -- >> Open BlueDragon Public Mailing List >> http://www.openbluedragon.org/ http://twitter.com/OpenBlueDragon >> official manual: http://www.openbluedragon.org/manual/ >> Ready2Run CFML http://www.openbluedragon.org/openbdjam/ >> >> mailing list - http://groups.google.com/group/openbd?hl=en >> > > -- Open BlueDragon Public Mailing List http://www.openbluedragon.org/ http://twitter.com/OpenBlueDragon official manual: http://www.openbluedragon.org/manual/ Ready2Run CFML http://www.openbluedragon.org/openbdjam/ mailing list - http://groups.google.com/group/openbd?hl=en
