Changing the user of a PersistentSession
Trying to implement a SQRL login for Websphere Commerce I ran in to the issue of changing the logged in user from another session.
To accomplish this I used the persistent sessions in commerce fetching an activity and changing what user ran in that session.
If you want to enable this behavior you need to first enable the persistentsessions in the running store.
UPDATE store SET persistentsession = 3 WHERE store_id = {runningStore};
After that you want to change the link on the page you know the customer will view before you change the session for them. In my perticular case I wanted to give them an option to logon on the login page. So I added
<wcf:url var="calcURL" value="OrderCalculate"> <wcf:param name="URL" value="LogonForm" /> </wcf:url> <wcf:url var="LogonFormURL" value="OrderItemMove"> <wcf:param name="langId" value="${param.langId}" /> <wcf:param name="storeId" value="${param.storeId}" /> <wcf:param name="catalogId" value="${param.catalogId}" /> <wcf:param name="URL" value="${calcURL}" /> </wcf:url>
This will ensure that the user will have a persisted session when he visits the logon page.
Then you need to specify the expiry time in days and if you want the persistent sessions for guests to be delayed. I found this to work best if I turned this of and 5 days seemed reasonable time to persist a cookie for a user.
<PersistentSession cookieExpiry ="5" delayNewPersistentGuestSession ="false" display= "false" enable ="true" />
When these params where set and I had restarted the server I just had to figure out code to enable this behavior. After a lot of searching in IBMs documentation I found a solution.
First we create a BusinessContextService and fetch the activity token for the user we want to login.
BusinessContextService bcs = ((BusinessContextService) BusinessContextServiceFactory.getBusinessContextService()); ActivityToken at = bcs.findActivityTokenForUserAndStore(oldUserId, storeId);
Then we create an empty Activity data to use on the transaction elevating the user.
ActivityData initData = new ActivityData();
Then we need to start a request with the server or else the change we make to the BaseContext won't be persisted.
bcs.begin(initData); bcs.startRequest(at, initData);
Lastly we fetch the BaseContext change both the CallerId and RunAsId (might not be needed but just in case I do both).
BaseContext ctx = (BaseContext)bcs.findContext(at, "com.ibm.commerce.context.base.BaseContext" ); ctx.setCallerId(newUserId); ctx.setRunAsId(newUserId);
Lastly we end the request so the user could make another request in their new context.
bcs.endRequest(at);
These steps will change the user running in the session of the old user to a new user id. In my case I elevate a guest user to a logged in normal user.
References
http://pic.dhe.ibm.com/infocenter/wchelp/v7r0m0/index.jsp?topic=%2Fcom.ibm.commerce.admin.doc%2Fconcepts%2Fcsepersist_session.htm
http://pic.dhe.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=%2Fcom.ibm.commerce.developer.doc%2Fconcepts%2Fcsdbcsbcm.htm
http://pic.dhe.ibm.com/infocenter/wchelp/v7r0m0/index.jsp?topic=%2Fcom.ibm.commerce.api.doc%2Fcom%2Fibm%2Fcommerce%2Fcomponent%2Fcontextservice%2FBusinessContextService.html