Here is the first bit of my patch to enable web2py to handle a cookieless 
login and session reconnect:

1. in main.py around line 401

    static_file = False
    try:
        try:
            try:

change to

    static_file = False
    isSessionRecordCreated = False # dlypka mod
    try:
        try:
            try:

   

2. In main.py starting around line 526

                # ##################################################
                # try load session or create new session file
                # ##################################################

                if not env.web2py_disable_session:
                    session.connect(request, response)


change to

                # ##################################################
                # try load session or create new session file
                # ##################################################

                session.connect(request, response, db)  # dlypka mod - 
added ,db
                
                newsessionid = 0 # dlypka mod
                if 'sessioncookieval_fromweb2py' in request.post_vars:  # 
dlypka mod
                    newsessionid = session._try_store_in_db(request, 
response) # dlypka mod                
                
                if newsessionid > 0:   # dlypka mod               
                    isSessionRecordCreated = True;  # dlypka mod

3. then in main.py around line 551:

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

change to

                # ##################################################
                # on success, try store session in database
                # ##################################################
                if isSessionRecordCreated == False: # dlypka mod           
        
                    session._try_store_in_db(request, response)


4. In globals.py around line 348 

        """
        separate can be separate=lambda(session_name): session_name[-2:]
        and it is used to determine a session prefix.
        separate can be True and it is set to session_name[-2:]
        """        
       
change to

        """
        separate can be separate=lambda(session_name): session_name[-2:]
        and it is used to determine a session prefix.
        separate can be True and it is set to session_name[-2:]
        """        
        
        if "session_id_name" in response.keys():  # dlypka mod
            return  # dlypka mod - avoids unnecessary session.connect() 
coming from db.py 

5. In globals.py around line 624

            try:

                # Get session data out of the database
                (record_id, unique_key) = response.session_id.split(':')
                if record_id == '0':
                    raise Exception('record_id == 0')
                        # Select from database
                if not session_cookie_data:
                    rows = db(table.id == record_id).select()
                    # Make sure the session data exists in the database
                    if len(rows) == 0 or rows[0].unique_key != unique_key:
                        raise Exception('No record')
                    # rows[0].update_record(locked=True)
                    # Unpickle the data
                    session_data = cPickle.loads(rows[0].session_data)
                    self.update(session_data)


Change to

            try:

                # Get session data out of the database
                if 'sessioncookieval_fromweb2py' in request.post_vars:   # 
dlypka mod for cookieless  client
                    key = request.post_vars['sessioncookieval_fromweb2py'] 
 # dlypka e.g. '72:d602d501-877d-42aa-9b52-0e58a91b8336'
                else:
                    key =  response.session_id
                (record_id, unique_key) = key.split(':')
                record_id = int(record_idstr) # dlypka patch to use int 
instead of string for the id
                if record_id == 0: # dlypka patch to use int instead of 
string for the id
                    raise Exception, 'record_id == 0'
                        # Select from database
                if not session_cookie_data:
                    rows = db(table.id == record_id).select()
                    # Make sure the session data exists in the database
                    if len(rows) == 0 or rows[0].unique_key != unique_key:
                        raise Exception('No record')
                    # rows[0].update_record(locked=True)
                    # Unpickle the data
                    session_data = cPickle.loads(rows[0].session_data)
                    self.update(session_data)


6. In globals.py around line 713:

    def _try_store_in_db(self, request, response):
        # don't save if file-based sessions,
        # no session id, or session being forgotten
        # or no changes to session
        if response.session_storage_type != 'db' or not response.session_id 
\
                or self._forget or self._unchanged():
            return False

        table = response.session_db_table
        record_id = response.session_db_record_id
        unique_key = response.session_db_unique_key

        dd = dict(locked=False,
                  client_ip=request.client.replace(':', '.'),
                  modified_datetime=request.now,
                  session_data=cPickle.dumps(dict(self)),
                  unique_key=unique_key)
        if record_id:
            table._db(table.id == record_id).update(**dd)
        else:
            record_id = table.insert(**dd)

        cookies, session_id_name = response.cookies, 
response.session_id_name
        cookies[session_id_name] = '%s:%s' % (record_id, unique_key)
        cookies[session_id_name]['path'] = '/'
        return True

change to

    def _try_store_in_db(self, request, response):
        # don't save if file-based sessions,
        # no session id, or session being forgotten
        # or no changes to session
        if response.session_storage_type != 'db' or not response.session_id 
\
                or self._forget or self._unchanged():
            return 0

        table = response.session_db_table
        record_id = response.session_db_record_id
        unique_key = response.session_db_unique_key

        dd = dict(locked=False,
                  client_ip=request.client.replace(':', '.'),
                  modified_datetime=request.now,
                  session_data=cPickle.dumps(dict(self)),
                  unique_key=unique_key)
        if record_id:
            table._db(table.id == record_id).update(**dd)
        else:
            record_id = table.insert(**dd)
        response.session_record_id = record_id # dlypka mod - useful to 
pass back to a client which does not support cookies, such as PhoneGap
        cookies, session_id_name = response.cookies, 
response.session_id_name
        cookies[session_id_name] = '%s:%s' % (record_id, unique_key)
        cookies[session_id_name]['path'] = '/'
        return record_id


# ======== End of web2py changes by Dave Lypka ===============

In followup posting I will show how to write the controller to use this new 
functionality and lastly I will show
how to write the client app.

In my controller I created

def isloggedin_mobile()

and also

def login_mobile():

I will give the code in a followup posting later this week.

- Dave Lypka.

On Friday, November 16, 2012 11:17:53 PM UTC-6, dlypka wrote:
>
> I intend to create some sample code fragments.
> I will try to post something by Monday.
>
> On Thursday, November 15, 2012 9:16:09 PM UTC-6, Jim S wrote:
>>
>> I would be interested in learning more. do you have any samples you could 
>> share?
>> On Nov 15, 2012 8:52 PM, "dlypka" <[email protected]> wrote:
>>
>>> I recently devised some changes to globals.py and main.py to allow a 
>>> non-cookies client to log into web2py and keep the same
>>> session record between requests, just as a browser does. In my case the 
>>> client is a PhoneGap app and I hit web2py through
>>> HTTP. I store the web2py session record id on the client in HTML 5 local 
>>> storage, so that the client can sent it along with
>>> each request to tell web2py what session to reconnect to.  A similar 
>>> approach would probably work from a Windows App.
>>>
>>> On Thursday, November 15, 2012 4:34:22 PM UTC-6, Jim S wrote:
>>>>
>>>> My main concern is that with this being a desktop app that I don't want 
>>>> to have to keep the latest versions of those files on the client machines.
>>>>
>>>> I switched my desktop authorization to read the Windows username and 
>>>> then match it to a username in the auth_user table and rely on the Windows 
>>>> authentication to ensure that user is logged in properly.  I validate that 
>>>> they are on the proper domain and they are logged in with an id in the 
>>>> table.
>>>>
>>>> Now I don't need to worry about keep those files current on multiple 
>>>> clients.
>>>>
>>>> -Jim
>>>>
>>>> On Thursday, November 15, 2012 2:01:12 PM UTC-6, Niphlod wrote:
>>>>>
>>>>> ehm.... validators.py (if not all, just crypt and lazycrypt, plus 
>>>>> Validator original class), utils.py and pbkdf2 is all you need.
>>>>>
>>>>> On Thursday, November 15, 2012 6:32:03 PM UTC+1, Jim S wrote:
>>>>>>
>>>>>> Sounds like there is no easy way to do it.  I looked through that 
>>>>>> code and it seems pretty involved.  I was hoping to do this without 
>>>>>> needing 
>>>>>> the web2py libs and such.
>>>>>>
>>>>>> -Jim
>>>>>>
>>>>>> On Thursday, November 15, 2012 11:14:09 AM UTC-6, Niphlod wrote:
>>>>>>>
>>>>>>> https://github.com/web2py/**web2py/blob/master/gluon/**
>>>>>>> tools.py#L1776<https://github.com/web2py/web2py/blob/master/gluon/tools.py#L1776>
>>>>>>> that basically calls the validators attached by default to a 
>>>>>>> password field 
>>>>>>> https://github.com/web2py/**web2py/blob/master/gluon/**
>>>>>>> tools.py#L1479<https://github.com/web2py/web2py/blob/master/gluon/tools.py#L1479>
>>>>>>> i.e. you just have to import the validator CRYPT and check with that 
>>>>>>> passing the correct parameters
>>>>>>> https://github.com/web2py/**web2py/blob/master/gluon/**
>>>>>>> validators.py#L2659<https://github.com/web2py/web2py/blob/master/gluon/validators.py#L2659>
>>>>>>>
>>>>>>> PS: CRYPT was easier to follow before the introduction of the pdfbk2 
>>>>>>> algo, but it's quite straightforward if you are willing to cut off 
>>>>>>> backward-compatibility
>>>>>>>  (that required lazycrypt https://github.com/web2py/**
>>>>>>> web2py/blob/master/gluon/**validators.py#L2581<https://github.com/web2py/web2py/blob/master/gluon/validators.py#L2581>
>>>>>>> )
>>>>>>>
>>>>>>>  -- 
>>>  
>>>  
>>>  
>>>
>>

-- 



Reply via email to