I have a Grails (2.3.6) app that requires users to login before they can access the app. As soon as they login successfully, they are redirected to a landing page that displays their username in the top-right corner. I had this working nicely (or so I thought) with the following 3 pieces of code:
// myapp/grails-app/realms/myapp/MyAppRealm.groovy:
class MyAppRealm {
def onSuccessfulLogin(Principal principal) {
// Lots of code
// If I logged in successfully with a username of "user1", then principal.name will be "user1" here.
UserHolder.name = principal.name
// Lots more code
}
}
In the above code the onSuccessfulLogin()
method is executed if the authentication layer determines they logged in successfully. The principal.name
value is the authenticated username they logged in with. As you can see I store this value in a UserHolder
POGO which looks like:
class UserHolder {
static String name = null
static String getName() {
name
}
static void setName(String n) {
name = n
}
}
Then, in my GSP file:
// myapp/grails-app/views/page.gsp
You are logged in as ${UserHolder?.name}.
It was just reported to me that a tester logged in successfully, and a few minutes later, hit F5 and refreshed their screen, only to find that their username belonged to another tester! After looking at the code, the reason for this is obvious: UserHolder.name
is a static variable; only 1 instance of it will live on the server at any given point in time. So if user1
logs in, they'll see user1
as their username in the UI. But if user2
then logs in, User.name
now equals user2
, and if user1
refreshes their screen, they'll see user2
as their username.
So my next thought was to try and store principal.name
in a session variable like session.name = principal.name
:
// myapp/grails-app/realms/myapp/MyAppRealm.groovy:
class MyAppRealm {
def onSuccessfulLogin(Principal principal) {
// Lots of code
// If I logged in successfully with a username of "user1", then principal.name will be "user1" here.
session.name = principal.name
// Lots more code
}
}
...and then refer to it in the GSP like You are logged in as ${session.name}.
. The problem there is that I don't have access to session
from inside MyAppRealm.groovy
, and it's not easily injectable (unless anyone can think of how). So I ask: how can I "record" principal.name
over in MyAppRealm
, and then specify the correct username from inside the GSP?
I had a similar requirement in my Groovy and Grails app.Not really a direct answer to your solution but you can try something similar. This is what I did:
class UserController {
def register() {
if(request.method == 'POST') {
def u = new User()
u.properties[
'login',
'password',
'firstName',
'lastName',
] = params
if(u.save()) {
session.user = u
session.setMaxInactiveInterval(-1)
redirect(controller: "myController", action: "welcome")
}
}
And in my view, I used it as follows:
Welcome ${session?.user?.firstName}
My User domain class is as follows:
class User {
String login
String password
String firstName
String lastName
}
Hope it helps :)