login automatically with Grails & Acegi

2019-06-02 03:57发布

问题:

I'm using the Acegi plugin in my Grails app. After a user registers, he is redirected to an action that is protected. Therefore, he is shown the login form.

However, I would prefer if the user was automatically logged in as soon as he completes registration. It seems like I could achieve this by redirecting to the action that the login form uses

redirect(uri:"/j_acegi_security_check?j_username=${username}&j_password=${passed}")

But this would send a HTTP request to the client (and back to the server) which shows the user's password. Is there a way I can login automatically in a secure fashion?

Thanks, Don

回答1:

If you generate the controller classes for the spring security plugin (grails generate-registration) you'll see the following lines in RegisterController which does just what you want:

class RegisterController {

def daoAuthenticationProvider

    ...

    def save = {
        ...
        def auth = new AuthToken(person.username, params.passwd)
        def authtoken = daoAuthenticationProvider.authenticate(auth)
        SecurityContextHolder.context.authentication = authtoken
        redirect uri: '/'
    }

Be sure that params.passwd is the plain-text password (i.e. not hashed) and it works like a charm.



回答2:

I haven't tried this with non-test code, but this is the method that I created to log a user in within my integration tests (after building/saving the appropriate users/roles in my test setup):

import org.codehaus.groovy.grails.plugins.springsecurity.GrailsDaoAuthenticationProvider
import org.springframework.security.providers.UsernamePasswordAuthenticationToken
import org.springframework.security.context.SecurityContextHolder

...

def logInAsUser(username, password) {
    daoAuthenticationProvider.getUserCache().removeUserFromCache(username) 
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password)
    SecurityContextHolder.context.authentication = daoAuthenticationProvider.authenticate(token)
}

I construct and inject the authentication token in the security context. There might be a little more that you need to do to get your user logged in and past security, but this would be the start of whatever that is.

I'll actually need to do exactly what you're asking in a week or two for my current app, post back if you figure it out fully before I do :).



回答3:

This is Burt Beckwith's answer (not mine)

(It was left as a comment by Burt, but I think it deserves to be more prominent)

If you don't have the password, you can load the user via

def user = User.findByUsername(username) 

and setting the authority array in the 3-parameter constructor. Create the auths via

GrantedAuthority[] auths = user.authorities.collect { new GrantedAuthorityImpl(it.authority) }

Then you can omit the call to authenticate() and use:

SecurityContextHolder.context.authentication = new UsernamePasswordAuthenticationToken(username, 'unknown', auths)