本教程将教您如何使用 JDBC 数据源 和 H2 数据库来保护您的 Spring Boot 应用程序。 我们将创建一个带有两个方法端点的示例 REST 控制器,每个端点都可用于不同的角色。
让我们从包含以下方法的 REST 控制器开始:
@RestController
public class CustomerController {
@Autowired CustomerRepository repository;
@RequestMapping(
path = "/",
method = RequestMethod.GET,
produces = {"application/json"})
public List<Customer> findAll() {
return repository.getData();
}
@PostMapping(path = "/", consumes = "application/json", produces = "application/json")
public ResponseEntity<Customer> addCustomer(@RequestBody Customer customer) throws Exception {
repository.save(customer);
return new ResponseEntity<Customer>(customer, HttpStatus.CREATED);
}
}
这里是 SpringSecurityConfig,它扩展了 WebSecurityConfigurerAdapter。在 configAuthentication 中,我们指定我们将使用 jdbcAuthentication。数据库上的密码将使用 BCryptPasswordEncoder 存储。您可以在本教程中学习如何使用 BCryptPasswordEncoder 加密密码:使用 BCryptPasswordEncoder 加密您的密码
在 configure 方法中,我们声明了每个方法允许的角色:
@Configuration @EnableAutoConfiguration public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired DataSource dataSource;
@Autowired public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().passwordEncoder(new BCryptPasswordEncoder()).dataSource(dataSource);
}
@Override protected void configure(HttpSecurity http) throws Exception {
//HTTP Basic authentication
http.httpBasic().and().authorizeRequests().antMatchers(HttpMethod.GET, "/").hasRole("USER").antMatchers(HttpMethod.POST, "/").hasRole("ADMIN").and().csrf().disable().formLogin().disable();
}
}
如您所见,我们没有指定任何存储用户名、密码和角色的表/关系。事实上,我们将使用默认的表和字段名称,它们是:
因此,我们将在资源文件夹中添加两个 sql 脚本。 Schema.sql 用于创建上述表,data.sql 用于插入一些用户:
这是schema.sql:
create table USERS( username varchar(128) not null primary key, password varchar(512) not null, enabled boolean not null); create table AUTHORITIES ( username varchar(128) not null, authority varchar(128) not null); create unique index idx_auth_username on authorities (username,authority);
和data.sql:
insert into users (username, password, enabled) values ('adam', '$2a$10$Ptvs9mLVFuEOXC4ckHi1weHGLQ7bGwigKQR5Uk9/aONvmKYPnRl8m', true); insert into authorities (username, authority) values ('adam', 'ROLE_USER'); insert into users (username, password, enabled) values ('jeff', '$2a$10$SRzxfUhAPr3wDJwcIJ/b3ePcJlmaJWOZMafN0dDmAw0ispxdXFi6K', true); insert into authorities (username, authority) values ('jeff', 'ROLE_ADMIN');
以上用户的密码为“password1”和“password2”。它们已使用 BCryptPasswordEncoder 加密。
由于我们将在此示例中使用 H2 数据库,因此在 application.properties 文件中,我们将配置 Datasource 如下:
spring.datasource.url = jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE spring.datasource.username = sa spring.datasource.password = spring.datasource.driverClassName=org.h2.Driver spring.datasource.initialization-mode=always
最后,pom.xml 文件中需要这些依赖项:
<?xml version="1.0" encoding="UTF-8"?><project>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
让我们使用 TestRestTemplate 为上述端点编写一个测试:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class DemoApplicationTests {
private static final ObjectMapper om = new ObjectMapper();
//@WithMockUser is not working with TestRestTemplate
@Autowired private TestRestTemplate restTemplate;
@Test public void testCustomerList() throws Exception {
ResponseEntity < String > response = restTemplate.withBasicAuth("adam", "password1").getForEntity("/", String.class);
printJSON(response);
//Verify user is authorized and content is JSON
assertEquals(MediaType.APPLICATION_JSON_UTF8, response.getHeaders().getContentType());
assertEquals(HttpStatus.OK, response.getStatusCode());
Customer c = new Customer(3, "Adam");
ResponseEntity < String > result = restTemplate.withBasicAuth("adam", "password1").postForEntity("/", c, String.class);
//Verify user is unauthorized
Assert.assertEquals(403, result.getStatusCodeValue());
//Verify user is authorized
result = restTemplate.withBasicAuth("jeff", "password2").postForEntity("/", c, String.class);
//Verify request succeed
Assert.assertEquals(201, result.getStatusCodeValue());
}
private static void printJSON(Object object) {
String result;
try {
result = om.writerWithDefaultPrettyPrinter().writeValueAsString(object);
System.out.println(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
在这个测试中,我们将检查:
您可以使用以下命令运行它:
mvn clean install
您刚刚学习了如何使用带有 H2 数据库的 JDBC 来保护您的 Spring Boot 应用程序。 如果您想切换到另一个数据库,只需针对其方言调整 sql 脚本并在 pom.xml 和application.properties 中的数据源配置。
本教程的源代码可在此处获得:https://github.com/fmarchioni/masterspringboot/tree/master/security/rest-jdbc-security
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
内容来源于网络,如有侵权,请联系作者删除!