Grails openid插件2.0.0 RC1:获取;无此类属性:用户例外;

Grails openid插件2.0.0 RC1:获取;无此类属性:用户例外;,grails,plugins,openid,Grails,Plugins,Openid,在我的grails应用程序中安装了2.0.0 RC1,但是 没有这样的属性:用户异常。有人能建议应该做什么吗 | Error 2013-10-28 00:11:55,169 [http-bio-8080-exec-6] ERROR errors.GrailsExceptionResolver - MissingPropertyException occurred when processing request: [POST] /Test/login/openIdCreateAccount -

在我的grails应用程序中安装了2.0.0 RC1,但是 没有这样的属性:用户异常。有人能建议应该做什么吗

| Error 2013-10-28 00:11:55,169 [http-bio-8080-exec-6] ERROR errors.GrailsExceptionResolver  - MissingPropertyException occurred when processing request: [POST] /Test/login/openIdCreateAccount - parameters:
username: valid_gmail@gmail.com
password2: ***
password: ***
No such property: User for class: grails.plugin.springsecurity.openid.OpenIdRegisterCommand. Stacktrace follows:
Message: No such property: User for class: grails.plugin.springsecurity.openid.OpenIdRegisterCommand
   Line | Method
->> 265 | doCall   in grails.plugin.springsecurity.openid.OpenIdRegisterCommand$__clinit__closure1_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|    63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
|    53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|    49 | doFilter in grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter
|    82 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|   895 | runTask  in java.util.concurrent.ThreadPoolExecutor$Worker
|   918 | run      in     ''
^   695 | run . .  in java.lang.Thread

这是一个bug,我修复了它并发布了2.0-RC2。请更新到该版本,看看它是否有效。

这是适合我的版本。你能基于这个插件发布一个新的RC3吗

/* Copyright 2013 SpringSource.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package grails.plugin.springsecurity.openid

import grails.plugin.springsecurity.SpringSecurityUtils
import grails.plugin.springsecurity.annotation.Secured

import org.springframework.beans.factory.InitializingBean
import org.springframework.orm.hibernate3.SpringSessionContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.AuthenticationException

/**
 * Manages associating OpenIDs with application users, both by creating a new local user
 * associated with an OpenID and also by associating a new OpenID to an existing account.
 */
@Secured('permitAll')
class OpenIdController implements InitializingBean {

    /** Dependency injection for daoAuthenticationProvider. */
    def daoAuthenticationProvider

    /** Dependency injection for the grailsApplication. */
    def grailsApplication

    /** Dependency injection for OpenIDAuthenticationFilter. */
    def openIDAuthenticationFilter

    /** Dependency injection for the requestCache. */
    def requestCache

    /** Dependency injection for the springSecurityService. */
    def springSecurityService

    private Class User
    private Class UserRole
    private Class Role
    private String usernamePropName
    private String passwordPropertyName
    private String enabledPropertyName
    private String roleNameField

    static defaultAction = 'auth'
    static scope = 'singleton'

    /**
     * Shows the login page. The user has the choice between using an OpenID and a username
     * and password for a local account. If an OpenID authentication is successful but there
     * is no corresponding local account, they'll be redirected to createAccount to create
     * a new account, or click through to linkAccount to associate the OpenID with an
     * existing local account.
     */
    def auth() {

        def config = SpringSecurityUtils.securityConfig

        if (springSecurityService.isLoggedIn()) {
            redirect uri: config.successHandler.defaultTargetUrl
            return
        }

        [openIdPostUrl: "$request.contextPath$openIDAuthenticationFilter.filterProcessesUrl",
         daoPostUrl:    "$request.contextPath$config.apf.filterProcessesUrl",
         persistentRememberMe: config.rememberMe.persistent,
         rememberMeParameter: config.rememberMe.parameter,
         openidIdentifier: config.openid.claimedIdentityFieldName]
    }

    /**
     * Initially we're redirected here after a UserNotFoundException with a valid OpenID
     * authentication. This action is specified by the openid.registration.createAccountUri
     * attribute.
     * <p/>
     * The GSP displays the OpenID that was received by the external provider and keeps it
     * in the session rather than passing it between submits so the user has no opportunity
     * to change it.
     */
    def createAccount(OpenIdRegisterCommand command) {

        String openId = session[OpenIdAuthenticationFailureHandler.LAST_OPENID_USERNAME]
        if (!openId) {
            flash.error = 'Sorry, an OpenID was not found'
            return [command: command]
        }

        if (!request.post) {
            // show the form
            command.clearErrors()
            copyFromAttributeExchange command
            return [command: command, openId: openId]
        }

        if (command.hasErrors()) {
            return [command: command, openId: openId]
        }

        if (!createNewAccount(command.username, command.password, openId)) {
            return [command: command, openId: openId]
        }

        authenticateAndRedirect command.username
    }

    /**
     * The registration page has a link to this action so an existing user who successfully
     * authenticated with an OpenID can associate it with their account for future logins.
     */
    def linkAccount(OpenIdLinkAccountCommand command) {

        String openId = session[OpenIdAuthenticationFailureHandler.LAST_OPENID_USERNAME]
        if (!openId) {
            flash.error = 'Sorry, an OpenID was not found'
            return [command: command]
        }

        if (!request.post) {
            // show the form
            command.clearErrors()
            return [command: command, openId: openId]
        }

        if (command.hasErrors()) {
            return [command: command, openId: openId]
        }

        try {
            registerAccountOpenId command.username, command.password, openId
        }
        catch (AuthenticationException e) {
            flash.error = 'Sorry, no user was found with that username and password'
            return [command: command, openId: openId]
        }

        authenticateAndRedirect command.username
    }

    /**
     * Authenticate the user for real now that the account exists/is linked and redirect
     * to the originally-requested uri if there's a SavedRequest.
     *
     * @param username the user's login name
     */
    protected void authenticateAndRedirect(String username) {
        session.removeAttribute OpenIdAuthenticationFailureHandler.LAST_OPENID_USERNAME
        session.removeAttribute OpenIdAuthenticationFailureHandler.LAST_OPENID_ATTRIBUTES

        springSecurityService.reauthenticate username

        def config = SpringSecurityUtils.securityConfig
        def savedRequest = requestCache.getRequest(request, response)
        if (savedRequest && !config.successHandler.alwaysUseDefault) {
            redirect url: savedRequest.redirectUrl
        }
        else {
            redirect uri: config.successHandler.defaultTargetUrl
        }
    }

    /**
     * Create the user instance and grant any roles that are specified in the config
     * for new users.
     * @param username  the username
     * @param password  the password
     * @param openId  the associated OpenID
     * @return  true if successful
     */
    protected boolean createNewAccount(String username, String password, String openId) {
        boolean created = User.withTransaction { status ->
            def config = SpringSecurityUtils.securityConfig

            password = encodePassword(password)
            def user = User.newInstance((usernamePropName): username,
                                        (passwordPropertyName): password,
                                        (enabledPropertyName): true)

            user.addToOpenIds(url: openId)

            if (!user.save()) {
                return false
            }

            for (roleName in config.openid.registration.roleNames) {
                UserRole.create user, Role.findWhere((roleNameField): roleName)
            }
            return true
        }
        return created
    }

    protected String encodePassword(String password) {
        def config = SpringSecurityUtils.securityConfig
        def encode = config.openid.encodePassword
        if (!(encode instanceof Boolean)) encode = false
        if (encode) {
            password = springSecurityService.encodePassword(password)
        }
        password
    }

    /**
     * Associates an OpenID with an existing account. Needs the user's password to ensure
     * that the user owns that account, and authenticates to verify before linking.
     * @param username  the username
     * @param password  the password
     * @param openId  the associated OpenID
     */
    protected void registerAccountOpenId(String username, String password, String openId) {
        // check that the user exists, password is valid, etc. - doesn't actually log in or log out,
        // just checks that user exists, password is valid, account not locked, etc.
        daoAuthenticationProvider.authenticate new UsernamePasswordAuthenticationToken(username, password)

        User.withTransaction { status ->
            def user = User.findWhere((usernamePropName): username)
            user.addToOpenIds(url: openId)
            if (!user.validate()) {
                status.setRollbackOnly()
            }
        }
    }

    /**
     * For the initial form display, copy any registered AX values into the command.
     * @param command  the command
     */
    protected void copyFromAttributeExchange(OpenIdRegisterCommand command) {
        List attributes = session[OpenIdAuthenticationFailureHandler.LAST_OPENID_ATTRIBUTES] ?: []
        for (attribute in attributes) {
            // TODO document
            String name = attribute.name
            if (command.hasProperty(name)) {
                command."$name" = attribute.values[0]
            }
        }
    }

    void afterPropertiesSet() throws Exception {
        def conf = SpringSecurityUtils.securityConfig
        usernamePropName = conf.userLookup.usernamePropertyName
        passwordPropertyName = conf.userLookup.passwordPropertyName
        enabledPropertyName = conf.userLookup.enabledPropertyName
        roleNameField = conf.authority.nameField
        User = grailsApplication.getClassForName(conf.userLookup.userDomainClassName)
        UserRole = grailsApplication.getClassForName(conf.userLookup.authorityJoinClassName)
        Role = grailsApplication.getClassForName(conf.authority.className)
    }
}

class OpenIdRegisterCommand {

    String username = ""
    String password = ""
    String password2 = ""

    static constraints = {

        username blank: false, validator: { String username, command ->

            def User = grails.util.Holders.getGrailsApplication().getClassForName(SpringSecurityUtils.securityConfig.userLookup.userDomainClassName)

            User.withNewSession { session ->
                if (username) {
                    boolean exists = User.createCriteria().count {
                        eq SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName, username
                    }
                    if (exists) {
                        return 'openIdRegisterCommand.username.error.unique'
                    }
                }
            }
        }
        password blank: false, minSize: 8, maxSize: 64, validator: { password, command ->
            if (command.username && command.username.equals(password)) {
                return 'openIdRegisterCommand.password.error.username'
            }

            if (password && password.length() >= 8 && password.length() <= 64 &&
                    (!password.matches('^.*[a-zA-Z].*$') ||
                    !password.matches('^.*[0-9].*$') ||
                    !password.matches('^.*[!@#$%^&].*$'))
                ) {
                return 'openIdRegisterCommand.password.error.strength'
            }

        }
        password2 validator: { password2, command ->
            if (command.password != password2) {
                return 'openIdRegisterCommand.password2.error.mismatch'
            }
        }
    }
}

class OpenIdLinkAccountCommand {

    String username = ""
    String password = ""

    static constraints = {
        username blank: false
        password blank: false
    }
}
/*版权所有2013 SpringSource。
*
*根据Apache许可证2.0版(以下简称“许可证”)获得许可;
*除非遵守许可证,否则不得使用此文件。
*您可以通过以下方式获得许可证副本:
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*除非适用法律要求或书面同意,软件
*根据许可证进行的分发是按“原样”进行分发的,
*无任何明示或暗示的保证或条件。
*请参阅许可证以了解管理权限和权限的特定语言
*许可证下的限制。
*/
包grails.plugin.springsecurity.openid
导入grails.plugin.springsecurity.SpringSecurityUtils
导入grails.plugin.springsecurity.annotation.securied
导入org.springframework.beans.factory.InitializingBean
导入org.springframework.orm.hibernate3.SpringSessionContext;
导入org.springframework.security.authentication.UsernamePasswordAuthenticationToken
导入org.springframework.security.core.AuthenticationException
/**
*通过创建新的本地用户来管理OpenID与应用程序用户的关联
*与OpenID关联,也可以通过将新OpenID关联到现有帐户。
*/
@安全('permitAll')
类OpenIdController实现初始化bean{
/**daoAuthenticationProvider的依赖项注入*/
def daoAuthenticationProvider
/**grailsApplication的依赖项注入*/
def grailsApplication
/**OpenIDAuthenticationFilter的依赖项注入*/
def openIDAuthenticationFilter
/**requestCache的依赖项注入*/
def请求缓存
/**springSecurityService的依赖项注入*/
def springSecurityService
私有类用户
私有类用户角色
私有类角色
私有字符串usernamePropName
私有字符串passwordPropertyName
私有字符串enabledPropertyName
私有字符串角色名称字段
静态defaultAction='auth'
静态作用域='singleton'
/**
*显示登录页面。用户可以选择使用OpenID和用户名
*和本地帐户的密码。如果OpenID身份验证成功,但
*没有相应的本地帐户,它们将被重定向到CreateCount进行创建
*新帐户,或单击链接帐户以将OpenID与
*现有本地帐户。
*/
def auth(){
def config=SpringSecurityUtils.securityConfig
if(springSecurityService.isLoggedIn()){
重定向uri:config.successHandler.defaultTargetUrl
返回
}
[openIdPostUrl:$request.contextPath$openIDAuthenticationFilter.FilterProcessURL”,
DAOPostrl:“$request.contextPath$config.apf.FilterProcessURL”,
persistentRememberMe:config.rememberMe.persistent,
rememberMe参数:config.rememberMe.parameter,
openidIdentifier:config.openid.claimedIdentityFieldName]
}
/**
*最初,我们在带有有效OpenID的UserNotFoundException之后重定向到这里
*身份验证。此操作由openid.registration.createAccountUri指定
*属性。
*

*GSP显示外部提供者接收到的OpenID并保存它 *在会话中,而不是在提交之间传递,因此用户没有机会 *改变它。 */ def CreateCount(OpenIdRegisterCommand命令){ 字符串openId=会话[OpenIdAuthenticationFailureHandler.LAST\u openId\u用户名] 如果(!openId){ flash.error='抱歉,找不到OpenID' 返回[命令:命令] } 如果(!request.post){ //出示表格 command.clearErrors() copyFromAttributeExchange命令 return[command:command,openId:openId] } if(command.hasErrors()){ return[command:command,openId:openId] } 如果(!createNewAccount(command.username、command.password、openId)){ return[command:command,openId:openId] } authenticateAndRedirect命令.username } /** *注册页面有一个指向此操作的链接,因此成功注册的现有用户 *使用OpenID进行身份验证可以将其与他们的帐户关联,以便将来登录。 */ def linkAccount(OpenIDLINKACCOUNT命令){ 字符串openId=会话[OpenIdAuthenticationFailureHandler.LAST\u openId\u用户名] 如果(!openId){ flash.error='抱歉,找不到OpenID' 返回[命令:命令] } 如果(!request.post){ //出示表格 command.clearErrors() return[command:command,openId:openId] } if(command.hasErrors()){ return[command:command,openId:openId] } 试一试{ registerAccountOpenId command.username、command.password、openId } 捕获(身份验证异常e){ flash.error='抱歉,找不到具有该用户名和密码的用户' return[command:command,openId:openId] } authenticateAndRedirect命令.username } /** *现在帐户已存在/已链接并重定向,请验证用户的真实身份 *如果存在SavedRequest,则返回最初请求的uri。 * *@param username用户的登录名 */ 受保护无效真实

(!password.matches('^.*[a-zA-Z].*$') ||
!password.matches('^.*[0-9].*$') ||
!password.matches('^.*[!@#$%^&].*$')))