I've created my own login objects, classes, and pages where I keep track of users, and when they log on, I create my own SessionId
and store the info in an object
+ a client side Cookie
. Then, I have a method (used in the Action
parameter of apex:page
) that validates my session for every Portal Site page
visited.
I too have multiple sites for a single org with users existing among all of my portals
. I differentiate Portal sessions
by the unique cookie name
for that particular Portal (+ the record
where the Session info is stored).
If you'd like to know more about my setup (including some code
), let me know, and I can post some details.
Some Details:
We manage multiple orgs, and each org may contain a number of Sites. Additionally, each site generally uses different sObjects
as "User records" (e.g. the associated user record is an Account
record or Employee__c
record). So, after creating a handful of Sites (custom portals for different client needs), each with their own login page & home page & ..., I began to see how to generealize this process.
It's split into a few steps:
Step 0:
For security, when a user logs in, a SessionID
is created (a long randomly generated string) and is stored in a Cookie (along with the User's username). Then, whenever the user navigates to any of the other site pages, I first call a method in the action
attribute of apex:page
that verifies the SessionID
(along with checking the SessionID
isn't "too old").
I had to create code to do this function (obviously), and I realized this process could be generalized. (more to come about this below)
Step 1:
Since each "User record" may belong to a different sObject, and I want to use this code across many orgs (not necessarily sharing the same custom sObjects), I needed to dissociate the "User records" from the Username__c
, Password__c
, Security-Questions, SessionID
data. So, I created a custom object called Portal__c
to house User-information and Session-data as well as Site-specific data accomplished by creating a number of RecordType
s for Portal__c
.
RecordType = Portal
: Houses Site parameters. e.g.
- Session
Cookie
Name
- Which Site the record belongs to
- How long the allowable Session Length should be (before requiring the user to re-login.)
- Which sObject designates the "User Record" (along with noting what the User-
RecordType
is.)
- The name of the
lookup-field
in the Portal__c:User
(i.e. the Portal__c
record with the "User
" RecordType
) [more about the User RecordType
in a sec]
- I have a set of string fields called
Login_Page__c
, Home_Page__c
, Register_Page__c
, Error_Page__c
, Expiration_Page__c
, Forgot_Page__c
where I can set the name of the corresponding VF Page. (This allows for easy navigation.)
RecordType = User
:
Since each User record could be attached to different sObjects (like Account
or Employee__c
), we will need a lookup to each of these different sObjects. To make administration easier, I create a different "User"-RecordType
for each Site. (Tt is sufficient to have a different RecordType
per distinct User-record-sObject.) This is why I allow the Portal__c:User
records to have different RecordTypes
.
The Portal__c:User
records have:
- Username
- Password (encrypted)
- lookup to the associated "User Record"
- picklist of Security Questions
- Security Answer (encrypted)
RecordType = Session
:
Houses Session Data and has a lookup to the associated Portal__c:User record. Every time a user logs in, a new Portal__c:Session
record is created.
There's not much here:
- SessionID (encrypted)
- lookup to Portal__c:User record
- Long Text Area field to house the Session History (an attempt to reduce the # of records created since the cost of each record is independent to how much data is stored within it). I have code that writes the Session History to this field whenever a User navigates through the Site.
Step 2:
I created an Apex class called Portal
to manage all this Portal and User information in a really easy-to-use way. In fact, it mimics some of the functionality of ApexPages.StandardControllers
:
- I wrote a lot of back end code to manage creating and verifying the Portal Sessions.
- Whenever a user navigates to a Site page, a new
Portal
instance is created, and it collects all the relevant data.
- The instance gives you the associated
User-record
and id
just like a StandardController
would.
- It's very easy to verify the SessionID, and if it is invalid, it redirects to the LOGIN page automatically.
- There are tools to navigate to different pages.
E.g.:
Portal portal = new Portal('mySiteName');
pageReference goHome = portal.getPage(Portal.Page.HOME);
id myRecordId = portal.getUserId();
pageReference verifySessionResult = portal.getSessionCheck();
pageReference theLoginPage = portal.loginPage(); // an easy escape to the login page
That's essentially it. It's really cool because it's a breeze to create new portal! The only real-work is creating the VF pages.
I'm still tweaking everything, and there is definitely room for improvement.