Grails 3.1.7 Spring 通过 GORM 脚手架创建新用户时的安全问题
Grails 3.1.7 Spring Security Issue when create new User by GORM Scaffolding
我正在做我在 Grails (版本 3.1.7) 中的第一步,我正在做一个需要用户身份验证的应用程序。这个应用程序是一个网络应用程序,也提供一些 REST 功能,所以我需要一个网络登录和一个 "rest" 使用令牌登录。
我正在使用 spring-security-core:3.1.0 和 spring-security-rest:2.0.0 .M2 对于这些建议,两个登录都正常工作。
现在,当我尝试通过 grails generate-all package.User
生成的 CRUD 创建新用户时遇到了一些麻烦,我正确生成了视图(我有一个用户可以拥有的客户端 class或者如果用户拥有它,我也会在同一个创建部分中提供客户端字段,因为客户端只能有一个用户)。保存时出现内部服务器错误 500:
URI/web/webUser/save,Classjava.lang.NullPointerException, 消息 null
在文件中:\web\WebUserController.groovy
该行是:webUser.save flush:true
轨迹是:
Line | Method
80 | doFilter in grails.plugin.springsecurity.rest.RestLogoutFilter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 64 | doFilter in grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 143 | doFilter in grails.plugin.springsecurity.rest.RestAuthenticationFilter
| 62 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 58 | doFilter in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . in java.lang.Thread
Caused by NullPointerException: null
->> 47 | $tt__save in WebUserController.groovy
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 96 | doInTransaction in grails.transaction.GrailsTransactionTemplate
| 93 | execute . in grails.transaction.GrailsTransactionTemplate
| 96 | doInTransaction in grails.transaction.GrailsTransactionTemplate
| 93 | execute . in grails.transaction.GrailsTransactionTemplate
| 80 | doFilter in grails.plugin.springsecurity.rest.RestLogoutFilter
| 64 | doFilter in grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 143 | doFilter in grails.plugin.springsecurity.rest.RestAuthenticationFilter
| 62 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 58 | doFilter in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run in java.lang.Thread
我不确定安全插件配置或用户和客户端域 class 或 userController 是否有问题。
编辑:更新信息!
@Transactional(readOnly = true)
class WebUserController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
static namespace = 'web'
def springSecurityService
@Transactional
def save(WebUser webUser) {
if (webUser == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (webUser.hasErrors()) {
transactionStatus.setRollbackOnly()
respond webUser.errors, view:'create'
return
}
webUser.save flush:true // line where the NullPointerException is threw
if (webUser.isAdmin){
UserRole.create webUser, Role.findByAuthority('ROLE_ADMIN')
} else {
UserRole.create webUser, Role.findByAuthority('ROLE_CLIENT')
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'webUser.label', default: 'WebUser'), webUser.id])
redirect webUser
}
'*' { respond webUser, [status: CREATED] }
}
}
域中的代码:
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['isAdmin', 'springSecurityService']
boolean isAdmin
Client client
String name
String email
Date lastVisit
static hasMany = [orders: BOrder]
static constraints = {
username size: 5..15, blank: false, unique: true
password size: 5..15, blank: false, password: true
email email: true, blank: false, unique: true
name size: 0..50, nullable: true
lastVisit nullable: true
client nullable: true
}
无论客户端是否为空,都会发生错误。如果我在 WebUser 域 class 中添加一个 afterInsert 进行调试,如果它不为 null,我可以看到生成的客户端 ID,但是没有生成 WebUser id,此时我没有看到任何错误消息。
嗯,我发现问题出在哪里了。
问题是我对密码大小添加了一个约束,并且在密码被散列之前执行了验证,所以验证通过,然后密码被散列并且它没有少于 15 个字符, 所以当它试图将用户保存在数据库中时失败,然后抛出空指针异常。
删除或更改密码的最大长度限制,问题已解决。
对我来说唯一奇怪的是我收到的错误消息,在我看来它没有说明任何相关内容。
我正在做我在 Grails (版本 3.1.7) 中的第一步,我正在做一个需要用户身份验证的应用程序。这个应用程序是一个网络应用程序,也提供一些 REST 功能,所以我需要一个网络登录和一个 "rest" 使用令牌登录。
我正在使用 spring-security-core:3.1.0 和 spring-security-rest:2.0.0 .M2 对于这些建议,两个登录都正常工作。
现在,当我尝试通过 grails generate-all package.User
生成的 CRUD 创建新用户时遇到了一些麻烦,我正确生成了视图(我有一个用户可以拥有的客户端 class或者如果用户拥有它,我也会在同一个创建部分中提供客户端字段,因为客户端只能有一个用户)。保存时出现内部服务器错误 500:
URI/web/webUser/save,Classjava.lang.NullPointerException, 消息 null
在文件中:\web\WebUserController.groovy 该行是:webUser.save flush:true
轨迹是:
Line | Method
80 | doFilter in grails.plugin.springsecurity.rest.RestLogoutFilter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 64 | doFilter in grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 143 | doFilter in grails.plugin.springsecurity.rest.RestAuthenticationFilter
| 62 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 58 | doFilter in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . in java.lang.Thread
Caused by NullPointerException: null
->> 47 | $tt__save in WebUserController.groovy
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 96 | doInTransaction in grails.transaction.GrailsTransactionTemplate
| 93 | execute . in grails.transaction.GrailsTransactionTemplate
| 96 | doInTransaction in grails.transaction.GrailsTransactionTemplate
| 93 | execute . in grails.transaction.GrailsTransactionTemplate
| 80 | doFilter in grails.plugin.springsecurity.rest.RestLogoutFilter
| 64 | doFilter in grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 143 | doFilter in grails.plugin.springsecurity.rest.RestAuthenticationFilter
| 62 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 58 | doFilter in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run in java.lang.Thread
我不确定安全插件配置或用户和客户端域 class 或 userController 是否有问题。
编辑:更新信息!
@Transactional(readOnly = true)
class WebUserController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
static namespace = 'web'
def springSecurityService
@Transactional
def save(WebUser webUser) {
if (webUser == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (webUser.hasErrors()) {
transactionStatus.setRollbackOnly()
respond webUser.errors, view:'create'
return
}
webUser.save flush:true // line where the NullPointerException is threw
if (webUser.isAdmin){
UserRole.create webUser, Role.findByAuthority('ROLE_ADMIN')
} else {
UserRole.create webUser, Role.findByAuthority('ROLE_CLIENT')
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'webUser.label', default: 'WebUser'), webUser.id])
redirect webUser
}
'*' { respond webUser, [status: CREATED] }
}
}
域中的代码:
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['isAdmin', 'springSecurityService']
boolean isAdmin
Client client
String name
String email
Date lastVisit
static hasMany = [orders: BOrder]
static constraints = {
username size: 5..15, blank: false, unique: true
password size: 5..15, blank: false, password: true
email email: true, blank: false, unique: true
name size: 0..50, nullable: true
lastVisit nullable: true
client nullable: true
}
无论客户端是否为空,都会发生错误。如果我在 WebUser 域 class 中添加一个 afterInsert 进行调试,如果它不为 null,我可以看到生成的客户端 ID,但是没有生成 WebUser id,此时我没有看到任何错误消息。
嗯,我发现问题出在哪里了。
问题是我对密码大小添加了一个约束,并且在密码被散列之前执行了验证,所以验证通过,然后密码被散列并且它没有少于 15 个字符, 所以当它试图将用户保存在数据库中时失败,然后抛出空指针异常。
删除或更改密码的最大长度限制,问题已解决。
对我来说唯一奇怪的是我收到的错误消息,在我看来它没有说明任何相关内容。