我正在使用 grails 2.1.0。我已经安装了 spring-security-core 插件。
当我创建用户时,它正在创建它。但是当我尝试登录时,它显示:
"Sorry, we were not able to find a user with that username and password." 
还有另一个事实是,当我为不同的用户使用相同的密码时,它不会像用户 1 那样保存具有相似编码值的密码 我使用123了像这样保存在数据库中的密码
d535ce213a0e8e4f9e724af47c46eea409ef401c03617b749da618a82890d743 
对于用户 2,我也使用了密码123,这次是这样保存的
0849ea79a2c1bca057ded06c3053fb5bc5d7ba52b50982e73e44894d4f3e0aa6
我不明白。谁能帮我解决这个问题?
我的 config.groovy >>>
    // locations to search for config files that get merged into the main config;
// config files can be ConfigSlurper scripts, Java properties files, or classes
// in the classpath in ConfigSlurper format
// grails.config.locations = [ "classpath:${appName}-config.properties",
//                             "classpath:${appName}-config.groovy",
//                             "file:${userHome}/.grails/${appName}-config.properties",
//                             "file:${userHome}/.grails/${appName}-config.groovy"]
// if (System.properties["${appName}.config.location"]) {
//    grails.config.locations << "file:" + System.properties["${appName}.config.location"]
// }
grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
grails.mime.use.accept.header = false
grails.mime.types = [
    all:           '*/*',
    atom:          'application/atom+xml',
    css:           'text/css',
    csv:           'text/csv',
    form:          'application/x-www-form-urlencoded',
    html:          ['text/html','application/xhtml+xml'],
    js:            'text/javascript',
    json:          ['application/json', 'text/json'],
    multipartForm: 'multipart/form-data',
    rss:           'application/rss+xml',
    text:          'text/plain',
    xml:           ['text/xml', 'application/xml']
]
// URL Mapping Cache Max Size, defaults to 5000
//grails.urlmapping.cache.maxsize = 1000
// What URL patterns should be processed by the resources plugin
grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
// The default codec used to encode data with ${}
grails.views.default.codec = "none" // none, html, base64
grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"
// enable Sitemesh preprocessing of GSP pages
grails.views.gsp.sitemesh.preprocess = true
// scaffolding templates configuration
grails.scaffolding.templates.domainSuffix = 'Instance'
// Set to false to use the new Grails 1.2 JSONBuilder in the render method
grails.json.legacy.builder = false
// enabled native2ascii conversion of i18n properties files
grails.enable.native2ascii = true
// packages to include in Spring bean scanning
grails.spring.bean.packages = []
// whether to disable processing of multi part requests
grails.web.disable.multipart=false
// request parameters to mask when logging exceptions
grails.exceptionresolver.params.exclude = ['password']
// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true')
grails.hibernate.cache.queries = false
environments {
    development {
        grails.logging.jul.usebridge = true
    }
    production {
        grails.logging.jul.usebridge = false
        // TODO: grails.serverURL = "http://www.changeme.com"
    }
}
// log4j configuration
log4j = {
    // Example of changing the log pattern for the default console appender:
    //
    //appenders {
    //    console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
    //}
    error  'org.codehaus.groovy.grails.web.servlet',        // controllers
           'org.codehaus.groovy.grails.web.pages',          // GSP
           'org.codehaus.groovy.grails.web.sitemesh',       // layouts
           'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
           'org.codehaus.groovy.grails.web.mapping',        // URL mapping
           'org.codehaus.groovy.grails.commons',            // core / classloading
           'org.codehaus.groovy.grails.plugins',            // plugins
           'org.codehaus.groovy.grails.orm.hibernate',      // hibernate integration
           'org.springframework',
           'org.hibernate',
           'net.sf.ehcache.hibernate'
}
// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'common.auth.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'common.auth.UserAuthority'
grails.plugins.springsecurity.authority.className = 'common.auth.Authority'
我的登录控制器 >>>
    import grails.converters.JSON
import javax.servlet.http.HttpServletResponse
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
class LoginController {
    /**
     * Dependency injection for the authenticationTrustResolver.
     */
    def authenticationTrustResolver
    /**
     * Dependency injection for the springSecurityService.
     */
    def springSecurityService
    /**
     * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
     */
    def index = {
        if (springSecurityService.isLoggedIn()) {
            redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
        } else {
            redirect action: 'auth', params: params
        }
    }
    /**
     * Show the login page.
     */
    def auth = {
        def config = SpringSecurityUtils.securityConfig
        if (springSecurityService.isLoggedIn()) {
            redirect uri: config.successHandler.defaultTargetUrl
            return
        }
        String view = 'auth'
        String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
        render view: view, model: [postUrl: postUrl,
                rememberMeParameter: config.rememberMe.parameter]
    }
    /**
     * The redirect action for Ajax requests.
     */
    def authAjax = {
        response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
        response.sendError HttpServletResponse.SC_UNAUTHORIZED
    }
    /**
     * Show denied page.
     */
    def denied = {
        if (springSecurityService.isLoggedIn() &&
                authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
            // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
            redirect action: 'full', params: params
        }
    }
    /**
     * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
     */
    def full = {
        def config = SpringSecurityUtils.securityConfig
        render view: 'auth', params: params,
                model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
                        postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
    }
    /**
     * Callback after a failed login. Redirects to the auth page with a warning message.
     */
    def authfail = {
        def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
        String msg = ''
        def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
        if (exception) {
            if (exception instanceof AccountExpiredException) {
                msg = g.message(code: "springSecurity.errors.login.expired")
            } else if (exception instanceof CredentialsExpiredException) {
                msg = g.message(code: "springSecurity.errors.login.passwordExpired")
            } else if (exception instanceof DisabledException) {
                msg = g.message(code: "springSecurity.errors.login.disabled")
            } else if (exception instanceof LockedException) {
                msg = g.message(code: "springSecurity.errors.login.locked")
            } else {
                msg = g.message(code: "springSecurity.errors.login.fail")
            }
        }
        if (springSecurityService.isAjax(request)) {
            render([error: msg] as JSON)
        } else {
            flash.message = msg
            redirect action: 'auth', params: params
        }
    }
    /**
     * The Ajax success redirect url.
     */
    def ajaxSuccess = {
        render([success: true, username: springSecurityService.authentication.name] as JSON)
    }
    /**
     * The Ajax denied redirect url.
     */
    def ajaxDenied = {
        render([error: 'access denied'] as JSON)
    }
}
我的权威.groovy >>>
    package common.auth
class Authority {
    String authority
    static mapping = {
        cache true
    }
    static constraints = {
        authority blank: false, unique: true
    }
}
我的用户 domain.groovy 我的用户将被保存在哪里 >>>
    package common.auth
class User {
    transient springSecurityService
    String realname
    String username
    String password
    String designation
    boolean enabled
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired
    static constraints = {
        username blank: false, unique: true
        password blank: false
    }
    static mapping = {
        password column: '`password`'
    }
    Set<Authority> getAuthorities() {
        UserAuthority.findAllByUser(this).collect { it.authority } as Set
    }
    def beforeInsert() {
        encodePassword()
    }
    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }
    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}
我的 userauthority.groovy >>>
    package common.auth
import org.apache.commons.lang.builder.HashCodeBuilder
class UserAuthority implements Serializable {
    User user
    Authority authority
    boolean equals(other) {
        if (!(other instanceof UserAuthority)) {
            return false
        }
        other.user?.id == user?.id &&
            other.authority?.id == authority?.id
    }
    int hashCode() {
        def builder = new HashCodeBuilder()
        if (user) builder.append(user.id)
        if (authority) builder.append(authority.id)
        builder.toHashCode()
    }
    static UserAuthority get(long userId, long authorityId) {
        find 'from UserAuthority where user.id=:userId and authority.id=:authorityId',
            [userId: userId, authorityId: authorityId]
    }
    static UserAuthority create(User user, Authority authority, boolean flush = false) {
        new UserAuthority(user: user, authority: authority).save(flush: flush, insert: true)
    }
    static boolean remove(User user, Authority authority, boolean flush = false) {
        UserAuthority instance = UserAuthority.findByUserAndAuthority(user, authority)
        if (!instance) {
            return false
        }
        instance.delete(flush: flush)
        true
    }
    static void removeAll(User user) {
        executeUpdate 'DELETE FROM UserAuthority WHERE user=:user', [user: user]
    }
    static void removeAll(Authority authority) {
        executeUpdate 'DELETE FROM UserAuthority WHERE authority=:authority', [authority: authority]
    }
    static mapping = {
        id composite: ['authority', 'user']
        version false
    }
}
而我在 AdministratorActionController 中创建用户的 createUser 操作 >>>
    package administrator
import common.auth.User
class AdmistratorActionController {
    def springSecurityService
    def index() {
           redirect(controller: 'admistratorAction', action: 'createUser')
    }
    def createUser = {
                User user = new User(params)
                def password = user.password
                def salt = user.username //depends on what you're using as a salt
                user.password = springSecurityService.encodePassword(password, salt)
                user.save()
                flash.message = "User Create Successfully !!!"
    }
}