如何使用 Spring-Boot 播种 Spring-Security
Posted
技术标签:
【中文标题】如何使用 Spring-Boot 播种 Spring-Security【英文标题】:How do I seed Spring-Security with Spring-Boot 【发布时间】:2014-08-02 07:21:13 【问题描述】:我有一个使用 Spring-Security spring-security-web:4.0.0.M1 的 spring-boot 1.1.0.BUILD-SNAPSHOT 项目。我想在我的 H2 表中植入数据库表,但在启动时出现异常(包括生产和集成测试代码)。
这是我相关的 schema.sql 文件内容:
CREATE TABLE IF NOT EXISTS Users (
username VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
password VARCHAR_IGNORECASE(500) NOT NULL,
enabled BOOLEAN NOT NULL
);
CREATE TABLE IF NOT EXISTS Authorities (
username VARCHAR_IGNORECASE(50) NOT NULL,
authority VARCHAR_IGNORECASE(50) NOT NULL,
CONSTRAINT fk_authorities_users FOREIGN KEY (username) REFERENCES users (username)
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_auth_username ON authorities (username, authority);
INSERT INTO users(username,password,enabled) VALUES ('admin','$2a$10$GVPAMYRozI08Mcll5too6.Q4M2jTO0iJVoiaVDv9pMxRqTpxNj9vO', TRUE);
INSERT INTO Authorities (username, authority) VALUES ('admin', 'ADMIN');
INSERT INTO users(username,password,enabled) VALUES ('user','$2a$10$GVPAMYRozI08Mcll5too6.Q4M2jTO0iJVoiaVDv9pMxRqTpxNj9vO', TRUE);
INSERT INTO Authorities (username, authority) VALUES ('user', 'USER');
我的 application.properties 文件中有以下内容:
spring.jpa.database=H2
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.generate-ddl=true
当我启动或运行测试时,我收到以下错误:
Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 1 of resource URL [file:/Users/David/projects/cnet/OFAC/out/test/OFAC/data.sql]: INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$GVPAMYRozI08Mcll5too6.Q4M2jTO0iJVoiaVDv9pMxRqTpxNj9vO', TRUE); nested exception is org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_4 ON PUBLIC.USERS(USERNAME)"; SQL statement:
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$GVPAMYRozI08Mcll5too6.Q4M2jTO0iJVoiaVDv9pMxRqTpxNj9vO', TRUE) [23505-172]
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:474)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:208)
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:49)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runScripts(DataSourceInitializer.java:135)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runDataScripts(DataSourceInitializer.java:95)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:88)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:46)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:98)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:333)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runSchemaScripts(DataSourceInitializer.java:78)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.initialize(DataSourceInitializer.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:349)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:300)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
用这些用户帐户播种安全数据库表的最佳方法是什么?我尝试了代码,但无法让加载程序以正确的顺序工作。
更新: 当我通过 ResourceDatabasePopulator.populate 时,我看到我有两个正在使用的 schema.sql 实例。他们是:
file:.../out/test/OFAC/schema.sql
file:.../out/production/OFAC/schema.sql
我也有:
file:.../out/test/OFAC/data.sql
file:.../out/production/OFAC/data.sql
显然没有重复 schema.sql 的危害。但是在 ScriptUtils.executeSqlScript() 中,我看到两个 data.sql 文件也被调用了。所以,我不明白为什么要执行测试和生产 sql 文件。
【问题讨论】:
看起来您的构建工具正在创建重复的类路径?我想你需要拨回一点,然后尝试一个非常简单的构建配置。 【参考方案1】:看起来您正在插入一条记录而没有提供主键。
另外(一旦你解决了这个问题),你将面临另一个问题:你可以使用schema.sql
或 spring.jpa.hibernate.ddl-auto=create-drop
,但不能同时使用。如果您愿意,除了create-drop
之外,您还可以将data.sql
用于DML(插入),然后您可以让Hibernate 创建表,并设置主键的自动生成(如果这是您想要的)。
顺便说一句:Boot 1.1.1.RELEASE 在 Maven Central 中,所以请使用它。
【讨论】:
戴夫,感谢您的反馈。我很确定我已经为我的 H2 表定义了主键,除非语法错误。由于我只插入一个唯一的记录,我不明白为什么会失败。我删除了 schema.sql 并让 Hibernate 负责生成,并将插入语句放入我的 data.sql 中。这似乎合乎逻辑。但是,当我删除 schema.sql 并使用“spring.jpa.hibernate.ddl-auto=create-drop”时,我得到 table not found 异常。 你使用的是 Boot 1.1.1 吗? 是的,当我使用 schema.sql、data.sql 和“spring.jpa.hibernate.ddl-auto=none”时,我切换到“springBootVersion = '1.1.1.RELEASE'”然后我回到唯一密钥违规。如果我使用“spring.jpa.hibernate.ddl-auto=create-drop”并删除 schema.sql,那么我找不到表。我更新了我的问题,发现重复的 data.sql 是明显的罪魁祸首。但我不知道如何解决这个问题以上是关于如何使用 Spring-Boot 播种 Spring-Security的主要内容,如果未能解决你的问题,请参考以下文章
我遇到了使用 spring-boot 2.0.2.RELEASE 进行 Hibernate/lucene 搜索的问题
让 oauth2 与 spring-boot 和 rest 一起工作