JDBC 认证

本文展示了如何使用 JDBC 的方式来进行认证。在本例,我们将认证信息存储于 H2 数据库中。

method-security项目的基础上,我们构建了一个jdbc-authentication项目。

注:有关 H2 的更多内容,可以参阅笔者的另外一部开源书《H2 Database 教程》

build.gradle

修改 build.gradle 文件,让我们的jdbc-authentication项目成为一个新的项目。

修改内容也比较简单,修改项目名称及版本即可。

  1. jar {
  2. baseName = 'jdbc-authentication'
  3. version = '1.0.0'
  4. }

处理依赖

添加 spring-boot-starter-jdbch2的依赖:

  1. // 添加 Spring Boot JDBC 的依赖
  2. compile('org.springframework.boot:spring-boot-starter-jdbc')
  3. // 添加 H2 的依赖
  4. runtime('com.h2database:h2:1.4.193')

修改配置文件

修改配置文件 application.properties :

  1. # 使用 H2 控制台
  2. spring.h2.console.enabled=true

修改配置类 SecurityConfig

在配置类中,添加对 H2 的过滤策略:

  1. http
  2. .authorizeRequests()
  3. .antMatchers("/css/**", "/js/**", "/fonts/**", "/index").permitAll() // 都可以访问
  4. .antMatchers("/h2-console/**").permitAll() // 都可以访问
  5. .antMatchers("/users/**").hasRole("USER") // 需要相应的角色才能访问
  6. .antMatchers("/admins/**").hasRole("ADMIN") // 需要相应的角色才能访问
  7. .and()
  8. .formLogin() //基于 Form 表单登录验证
  9. .loginPage("/login").failureUrl("/login-error") // 自定义登录界面
  10. .and()
  11. .exceptionHandling().accessDeniedPage("/403"); // 处理异常,拒绝访问就重定向到 403 页面
  12. http.logout().logoutSuccessUrl("/"); // 成功登出后,重定向到 首页
  13. http.csrf().ignoringAntMatchers("/h2-console/**"); // 禁用 H2 控制台的 CSRF 防护
  14. http.headers().frameOptions().sameOrigin(); // 允许来自同一来源的H2 控制台的请求

其中:

  • http.csrf().ignoringAntMatchers : 用于配置匹配的 URL,不进行 CSRF 防护。这里,我们不需要对 H2 控制台做 CSRF 防护
  • http.headers().frameOptions().sameOrigin() : 用于配置同源策略。允许来自同一来源的H2 控制台的请求

使用Spring JDBC初始化数据库

Spring JDBC 有一个 DataSource 初始化功能。 Spring Boot 默认启用它,并从标准位置(在类路径的根目录中)的schema.sqldata.sql 脚本中加载SQL。此外,Spring Boot将加载schema-${platform}.sqldata-${platform}.sql文件(如果存在的话),其中 platform 是 spring.datasource.platform的值,例如。您可以选择将其设置为数据库的供应商名称(hsqldb、h2、oracle、mysql、postgresql 等)。 Spring Boot 默认启用了 Spring JDBC 初始化程序中的快速失败(fail-fast)功能,因此,如果脚本导致异常,应用程序将无法启动。可以通过设置spring.datasource.schemaspring.datasource.data来更改脚本位置,如果spring.datasource.initialize=false,则不会处理任何位置的脚本。

要禁用快速失败(fail-fast)功能,您可以设置spring.datasource.continue-on-error=true。这在应用程序成熟并部署了几次后可能很有用,因为插入失败意味着数据已经存在,因此不需要阻止应用程序运行。

如果要在 JPA 应用程序(如使用Hibernate)中使用schema.sql初始化,那么如果 Hibernate 尝试创建相同的表,ddl-auto=create-drop将导致错误。要避免这些错误,请将 ddl-auto 显式设置为“”(首选)或“none”。无论是否使用ddl-auto=create-drop,您都可以使用 data.sql 初始化新数据。

我们的表结构写在了 schema.sql 中:

  1. create table users (
  2. username varchar(256),
  3. password varchar(256),
  4. enabled boolean
  5. );
  6. create table authorities (
  7. username varchar(256),
  8. authority varchar(256)
  9. );

我们的数据写在了 data.sql 中:

  1. insert into users (username, password, enabled) values ('waylau', '123456', true);
  2. insert into users (username, password, enabled) values ('admin', '123456', true);
  3. insert into authorities (username, authority) values ('waylau', 'ROLE_USER');
  4. insert into authorities (username, authority) values ('admin', 'ROLE_USER');
  5. insert into authorities (username, authority) values ('admin', 'ROLE_ADMIN');

访问 H2 控制台

设置 JDBC URL为 jdbc:h2:mem:testdb

JDBC 认证 - 图2

可以看到我们新建的数据库表和初始化的数据:

JDBC 认证 - 图3