B4J Question [ABMaterial] Need a tutorial on how to manage cookies (creation an usage)

Cableguy

Expert
Licensed User
Longtime User
Hi ABMaterial Gurus!

My webapp will have a register/login system, and I would like to add a "remember me" functionality, which I reckon i can/should do using cookies.
The problem is, I have a very basic understanding of what cookies are and how to use them, and no idea how to relate that info with ABMaterial!
So please, can someone give me a few pointers???
 

Cableguy

Expert
Licensed User
Longtime User
can you be a bit more specific? In which modules or sub should I bee looking?
 
Upvote 0

Harris

Expert
Licensed User
Longtime User
can you be a bit more specific? In which modules or sub should I bee looking?

ABMSessionCreator Class...

Search for "cookie"

B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
        '   WHAT HAPPENS HERE?
        '   when you connect to a site the browser send all the cookies (name and value) that it has stored for that site - in request Cookie header
        '    If browser has a cookie named JSESSIONID Then
        '        If the value of that cookie represents a valid server session id Then
        '            ' valid server session means that the server must have a session with that id, a session can not be valid anymore when
'              the session expiers or you restart the server and as sessions are stored in memory all that data will be lost.
        '            use that session object that has the session id And Continue
        '        Else
        '            create a new session object And set the Set-Cookie header in the response so that the browser can set a new value to the
'             JSESSIONID cookie
        '        End If
        '    Else
        '        create a new session object And set the Set-Cookie header in the response so that the browser can create a cookie named
'        JSESSIONID with value the id of the session object
        '    End If
        '   END WHAT HAPPENS HERE?
        req.GetSession
End Sub


ABMApplication...

B4X:
public Sub StartServer(srvr As Server, srvrName As String, srvrPort As Int)

  '----------------------MODIFICATION 3.20-------------------------------
Dim joServer As JavaObject = srvr
joServer.GetFieldJO("server").RunMethod("stop", Null)
joServer.GetFieldJO("context").RunMethodJO("getSessionHandler", Null).RunMethodJO("getSessionManager", Null).RunMethodJO("getSessionCookieConfig", Null).RunMethod("setMaxAge", Array(31536000)) ' 1 year
' NEW FEATURE! Each App has its own Session Cookie
joServer.GetFieldJO("context").RunMethodJO("getSessionHandler", Null).RunMethodJO("getSessionManager", Null).RunMethodJO("getSessionCookieConfig", Null).RunMethod("setName", Array(ABMShared.AppName.ToUpperCase))
joServer.GetFieldJO("server").RunMethod("start", Null)
'----------------------MODIFICATION 3.20-------------------------------
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
ABMSessionCreator Class...

Search for "cookie"

B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
        '   WHAT HAPPENS HERE?
        '   when you connect to a site the browser send all the cookies (name and value) that it has stored for that site - in request Cookie header
        '    If browser has a cookie named JSESSIONID Then
        '        If the value of that cookie represents a valid server session id Then
        '            ' valid server session means that the server must have a session with that id, a session can not be valid anymore when
'              the session expiers or you restart the server and as sessions are stored in memory all that data will be lost.
        '            use that session object that has the session id And Continue
        '        Else
        '            create a new session object And set the Set-Cookie header in the response so that the browser can set a new value to the
'             JSESSIONID cookie
        '        End If
        '    Else
        '        create a new session object And set the Set-Cookie header in the response so that the browser can create a cookie named
'        JSESSIONID with value the id of the session object
        '    End If
        '   END WHAT HAPPENS HERE?
        req.GetSession
End Sub


ABMApplication...

B4X:
public Sub StartServer(srvr As Server, srvrName As String, srvrPort As Int)

  '----------------------MODIFICATION 3.20-------------------------------
Dim joServer As JavaObject = srvr
joServer.GetFieldJO("server").RunMethod("stop", Null)
joServer.GetFieldJO("context").RunMethodJO("getSessionHandler", Null).RunMethodJO("getSessionManager", Null).RunMethodJO("getSessionCookieConfig", Null).RunMethod("setMaxAge", Array(31536000)) ' 1 year
' NEW FEATURE! Each App has its own Session Cookie
joServer.GetFieldJO("context").RunMethodJO("getSessionHandler", Null).RunMethodJO("getSessionManager", Null).RunMethodJO("getSessionCookieConfig", Null).RunMethod("setName", Array(ABMShared.AppName.ToUpperCase))
joServer.GetFieldJO("server").RunMethod("start", Null)
'----------------------MODIFICATION 3.20-------------------------------

That is the "default" code...
What I found that can be connected to it is this, inside the websocket_connected sub in the ABMApplication
B4X:
    If ABMShared.NeedsAuthorization Then
        If ws.Session.GetAttribute2("IsAuthorized", "") = "" Then
            Dim loginpwd As String = ABM.LoadLogin(AppPage, ABMShared.AppName)
            If loginpwd <> "" Then
                Dim SQL As SQL = DBM.GetSQL
                Dim split() As String = Regex.Split(";", loginpwd)
              
                Dim vars As List
                vars.Initialize
                vars.Add(split(0))
                vars.Add(split(1))
                Dim users As List = DBM.SQLSelect(SQL, "SELECT * FROM users WHERE UserLogin=? AND UserPassword=?", vars)
              
                'Dim users As List = DBM.SQLSelect(SQL, "SELECT * FROM users WHERE UserLogin='" & split(0) & "' AND UserPassword='" & split(1) & "'")
                If users.Size > 0 Then  
                    Dim user As Map = users.Get(0)
                    ws.Session.SetAttribute("authType", "local")
                    ws.Session.SetAttribute("authName", split(0))
                    ws.Session.SetAttribute("IsAuthorized", "true")
                    ws.Session.SetAttribute("UserType", "" & user.Get("usertype") )    ' lowercase!              
                    ws.Session.SetAttribute("UserID", "" & user.Get("userid") ) ' lowercase!                  
                    ABMShared.NavigateToPage(ws, ABMPageId, "./" & InitialPage)
                    DBM.CloseSQL(SQL)
                    Return  
                End If
                DBM.CloseSQL(SQL)
            End If
            AppPage.ShowModalSheet("login")
            Return
        End If
    End If

Am I on the right track?
should I, upon login use the ABM.setLogin method, so that upon the new reconnection I can read it and check for user existence?
 
Upvote 0

Harris

Expert
Licensed User
Longtime User
Yes. ie:

If session.GetAttribute2("IsAuthorized", "") = "" Then
ABMShared.NavigateToPage(ws, ABMPageId, "../")
Return
End If

Set whatever cookie you need.
 
Upvote 0

mindful

Active Member
Licensed User
@Cableguy you have to options for your remember me feature.

One is to create a cookie within a handler class that issues a cookie with something like a token as it's value and when the user connects you check if it has the token cookie and validate it's value. The only benefit I see from using this option is that you have the token stored in the browser (client). But this is kind of hard to get it working because ABMaterial uses websockets and apple devices have a problem when you set cookies from a websocket connection, also jServer with ABMaterial will always issue a session cookie (see below) so it's better to use the second option.

And the other option is to use session storage (this is implememted in Feedback app). Each session is kind of a map stored on a server and in the browser it stored as cookie with your app name (or JSESSIONID) and an indentifier. So basically each browser that connects to your app will get a session stored on the server and a session cookie on the browser. You can add your own logic to what you store in session (like keep a user authed for 3 days, keep the last page he accessed and redirect it to it on the next visit, etc...).

The down side of using the session object is that when you restart your app all the session data is lost. However you can setup session to be persistent to a file or mongodb or sql db, but that is another subject ;)

Also you need to take in account that browsers also save login details (if the user agrees with saving) like username and password and even if you do not have a remember me feature the fields will be autocompleted and all the user has to do is press login.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
Thanks @mindful,

Yesterday I took a deeper look at the feedback source and I think I understand what @alwaysbusy did to implement this feature (I found a session.savelogin and session loading methods) so I guess I will go that route.
Thanks all for your input!
 
Last edited:
Upvote 0
Top