我正在将SpringSecurity插件与应用程序集成。为此,我安装了插件并运行s2-quickstart脚本,该脚本创建了三个域类:SecUserSecRoleSecUserSecRole以及登录/注销 Controller 。

因为我已经有一个现有的User域类并希望保留它,所以我修改了User以扩展SecUser并从User中删除了用户名和密码的重叠字段。另外,我在用户和SecUser映射部分都添加了tablePerHierarchy false

在BootStrap中,我试图创建一个在启动时存在的Admin用户。为此,我创建了一个新的SecRole对象adminRole,其权限设置为ROLE_ADMIN。然后,我创建一个新的User对象,并通过以下命令检查它是否包含管理员角色

def springSecurityService
def init {
    def adminUser = User.findByUsername('admin') ?: new User(
        username:'admin',
        password:'adminUser',
        userType:'Admin',
        enabled:true
    ).save(failOnError:true)

    if (!adminUser.authorities.contains(adminRole))
        SecUserSecRole.create adminUser, adminRole, true

}

我的问题是,无论是否将adminUser声明为User或SecUser实例,我都会不断收到 transient 实例异常。由于userType的约束为blank:false,因此如果在创建User实例时我注释掉了userType字段,我会得到一个误解,指出null不是userType的有效设置。当包含它时,我得到了 transient 对象异常:对象引用了一个未保存的 transient 实例-在刷新之前保存该 transient 实例:books4africa.SecUser ,所以我知道我正在传递所有用户验证设置。

是什么原因导致在这种情况下无法保存有效的User对象?

编辑

解决此问题的方法是删除现有的dev数据库文件并重新初始化应用程序。我的猜测是,数据库和Spring Security与原始数据库之间存在某种冲突,因此使用新数据库重新启动应用程序解决了该问题。

由于以下所有答案均无法解决确切的问题,因此在这种情况下,我将不接受,但感谢您的帮助!

最佳答案

在我看来,域或您创建域实例的方式似乎存在问题。

你说:



但是也许您没有告诉插件您这样做。请看看documentation regarding the domain classes。要使用您自己的域,您必须配置SpringSecurity插件(该文档包含您需要的所有信息)。因此,例如,如果您想使用自己的用户类。您将这样的事情放在您的配置中:

grails.plugins.springsecurity.userLookup.userDomainClassName = 'your.package.NameOfYourClass'

这将告诉插件它必须为用户使用的类是NameOfYourClass

使用默认类很重要,例如,生成的快速入门是正确使用自定义Users和Roles类的最简单方法(只需将每个属性复制到自己的类中,然后根据需要进行重命名)。

并查看tutorials,以了解如何正确保存用户和角色。

10-06 01:22