我正在使用Grails 3.3.2和Spring Security Rest 2.0.0.M2和Spring Security Core 3.2.0。

它是基于权限的(AdminAccount>角色>权限),生成的域类是 AdminAccount,AdminAccountPermission,Permission,Role,AdminAccountRole,RolePermission

我还自定义了从s2-quickstart生成的类(AdminAccount属性>用户名到emailAddress)

application.groovy

grails {
    plugin {
        springsecurity {
            // securityConfigType = "InterceptUrlMap"
            userLookup.userDomainClassName = 'sec.core.acl.AdminAccount'
            userLookup.authorityJoinClassName = 'sec.core.acl.AdminAccountPermission'
            authority.className = 'sec.core.acl.Permission'
            authority.groupAuthorityNameField = 'authorities'
            useRoleGroups = true
            controllerAnnotations.staticRules = [
                [pattern: '/',               access: ['permitAll']],
                [pattern: '/error',          access: ['permitAll']],
                [pattern: '/index',          access: ['permitAll']],
                [pattern: '/index.gsp',      access: ['permitAll']],
                [pattern: '/shutdown',       access: ['permitAll']],
                [pattern: '/assets/**',      access: ['permitAll']],
                [pattern: '/**/js/**',       access: ['permitAll']],
                [pattern: '/**/css/**',      access: ['permitAll']],
                [pattern: '/**/images/**',   access: ['permitAll']],
                [pattern: '/**/favicon.ico', access: ['permitAll']],
                [pattern: '/cmdata/**', access: ['permitAll']],
                [pattern: '/api/login',             access: ['permitAll']],
                [pattern: '/oauth/access_token',    access: ['permitAll']],
            ]
            filterChain.chainMap = [
                [pattern: '/assets/**',      filters: 'none'],
                [pattern: '/**/js/**',       filters: 'none'],
                [pattern: '/**/css/**',      filters: 'none'],
                [pattern: '/**/images/**',   filters: 'none'],
                [pattern: '/**/favicon.ico', filters: 'none'],
                [pattern: '/api/**',filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter'],
                [pattern: '/**', filters: 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter']
            ]
            rest {
                login {
                    usernamePropertyName='emailAddress'
                    passwordPropertyName='password'
                }
                logout {
                    postOnly=false
                }
                token {
                    validation {
                        useBearerToken=false
                        eaderName='X-Auth-Token'
                        active=true
                    }
                }
            }
        }
    }
}

AdminAccount.groovy
package sec.core.acl

import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import grails.compiler.GrailsCompileStatic

@GrailsCompileStatic
@EqualsAndHashCode(includes='emailAddress')
@ToString(includes='emailAddress', includeNames=true, includePackage=false)
class AdminAccount implements Serializable {

    /** Injects springSecurityService in this domain class. */
    transient springSecurityService

    private static final long serialVersionUID = 1

    String emailAddress
    String password
    String resetKey
    boolean enabled = true
    boolean accountExpired = false
    boolean accountLocked = false
    boolean passwordExpired = false
    Date dateCreated = new Date()
    Date lastUpdated = new Date()

    static transients = ['springSecurityService']

    /** Defines ownership on class <code>AdminProfile</code> */
    static belongsTo = [profile: AdminProfile]

    Set<Permission> getAuthorities() {
        (AdminAccountPermission.findAllByAdminAccount(this) as List<AdminAccountPermission>)*.permission as Set<Permission>
    }

    static constraints = {
        password nullable: false, blank: false, password: true
        emailAddress nullable: false, blank: false, unique: true, matches: /^((?!(\..*|.*\.\@|.*\.\..*))(?=.*[0-9a-zA-Z._\Ñ\ñ].*)[0-9a-zA-Z._\Ñ\ñ]+)\@([a-zA-Z0-9]+)(\.[a-zA-Z0-9]+)+$/
        dateCreated blank: false
        lastUpdated blank: false, nullable: true
        resetKey nullable: true
    }

    static mapping = {
        table 'adm_account'
        emailAddress column: 'email_address', index: 'email_address_idx'
        password column: '`password`'
        dateCreated column: 'date_created'
        lastUpdated column: 'last_updated'
    }
}

然后,如果我尝试使用 curl 获取身份验证 token
curl -v -X POST -H "Content-Type: application/json" -d '{"emailAddress":"[email protected]","password":"password"}' http://localhost:8080/api/login

然后我收到401 的回复
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 61
>
* upload completely sent off: 61 out of 61 bytes
< HTTP/1.1 401
< Content-Length: 0
< Date: Fri, 30 Mar 2018 10:50:35 GMT
<
* Connection #0 to host localhost left intact

最佳答案

[已解决] 我忘记将 userLookup.usernamePropertyName ='emailAddress'添加到 application.groovy

10-06 01:22