Grails openid插件2.0.0 RC1:获取;无此类属性:用户例外;
在我的grails应用程序中安装了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 -
| 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('^.*[!@#$%^&].*$')))