在本教程中,我们将学习如何使用 Spring Boot 为简单的 REST 服务启用内存中基本身份验证。我们将为两个不同的用户配置不同的角色,并添加一个测试类来验证内存中的基本身份验证。
###新建一个Spring Boot项目
首先创建一个基本的 Spring Boot 项目,其中包括以下依赖项:
<?xml version="1.0" encoding="UTF-8"?><project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-rest-secured</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<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>
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring security test -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Spring 安全配置我在扩展WebSecurityConfigurerAdapter 的@Configuration Bean 中定义:
package com.example.testrest;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("{noop}password")
.roles("USER")
.and()
.withUser("admin")
.password("{noop}password")
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/**")
.hasRole("USER")
.antMatchers(HttpMethod.POST, "/")
.hasRole("ADMIN")
.and()
.csrf()
.disable()
.formLogin()
.disable();
}
}
如您所见,我们添加了两个角色:
另外,请注意,在上面的示例中,每个密码都有一个前缀 {x},它指定应该使用什么密码编码器来对提供的密码进行编码。以下是您可以用作密码前缀的不同值:
因此,为了使用 HTTP POST 方法,您需要“ADMIN”角色,而 HTTP GET 可以由“USER”角色执行。让我们添加一个带有 GET 和 POST 方法的 Controller 类:
package com.example.testrest;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
public class CustomerController {
@Autowired CustomerRepository repository;
@RequestMapping(
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);
}
}
Customer 类使用 CustomerRepository 来持久化 Customer 对象。在文章末尾查看此示例的完整代码。
您可以使用基本的 SpringBootApplication 运行该类:
package com.example.testrest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
为了测试它,我们可以使用 TestRestTemplate 类:
package com.example.testrest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class DemoApplicationTests {
private static final ObjectMapper om = new ObjectMapper();
@Autowired private TestRestTemplate restTemplate;
@Test public void testCustomerList() throws Exception {
ResponseEntity < String > response = restTemplate.withBasicAuth("user", "password").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("user", "password").postForEntity("/", c, String.class);
//Verify user is unauthorized
Assert.assertEquals(403, result.getStatusCodeValue()); //Verify user is authorized
result = restTemplate.withBasicAuth("admin", "password").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();
}
}
}
在这个测试中,我们执行一组断言。首先,我们使用“用户/密码”凭据执行 HTTP GET。然后,使用相同的凭据,我们尝试执行 HTTP POST。该测试预计会失败。最后,我们使用“admin/password”凭据再次执行 HTTP POST。这有望通过。
您可以使用以下命令运行上述测试:
mvn install
您应该看到测试方法成功完成:
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.755 s - in com.example.testrest.DemoApplicationTests
恭喜!您刚刚设法针对 REST 服务运行了 Spring 内存中身份验证的第一个基本示例。
完整源代码:https://github.com/fmarchioni/masterspringboot/tree/master/security/rest-inmemory-security
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
内容来源于网络,如有侵权,请联系作者删除!