Spring Boot中的Spring安全配置未按预期工作[重复]
Posted
技术标签:
【中文标题】Spring Boot中的Spring安全配置未按预期工作[重复]【英文标题】:Spring security configuration in spring boot not working as expected [duplicate] 【发布时间】:2021-11-23 11:41:34 【问题描述】:我正在使用带有 Spring Boot 的 Spring Security。但我的 spring 安全配置现在按预期工作。
注意:H2 数据库在服务器模式下作为单独的数据库运行(不在嵌入式模式下)。
这是我的项目详情:
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Application.properties
server.port=8085
spring.datasource.url=jdbc:h2:tcp://localhost:9092/mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
EmployeeeResource.java
@RestController
@RequestMapping("/employee")
@Slf4j
public class EmployeeResource
@Autowired
EmployeeRepository employeeRepository;
@GetMapping(path = "/greetEmployee", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello()
return "Hello Employee !!!";
@GetMapping(path = "/getAllEmployees", produces = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<List<Employee>> getAllEmployee()
List<Employee> employeeList = employeeRepository.findAll();
return new ResponseEntity<>(employeeList, HttpStatus.OK);
@GetMapping(path = "/getEmployee/employeeId", produces = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Employee> getEmployee(@PathVariable("employeeId") int employeeId)
Optional<Employee> optionalEmployee = employeeRepository.findByEmployeeId(employeeId);
if (optionalEmployee.isEmpty())
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(optionalEmployee.get(), HttpStatus.FOUND);
@PostMapping(path = "/createEmployee", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<HttpStatus> createEmployee(@RequestBody Employee employee)
Random random = new Random();
employee.setEmployeeId(random.nextInt(9999));
employeeRepository.save(employee);
log.info("Created employee with Id : ", employee.getEmployeeId());
return new ResponseEntity<>(HttpStatus.CREATED);
@PostMapping(path = "/createEmployees", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> createEmployees(@RequestBody List<Employee> employeeList)
int count = 0;
Random random = new Random();
for (Employee employee : employeeList)
employee.setEmployeeId(random.nextInt(999999));
employeeRepository.save(employee);
log.info("Created employee with Id : ", employee.getEmployeeId());
count++;
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("countOfObjectCreated", String.valueOf(count));
return ResponseEntity.status(HttpStatus.CREATED).headers(responseHeaders).build();
@PutMapping(path = "/updateEmployee/employeeId", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<HttpStatus> updateCustomer(@PathVariable("employeeId") int employeeId, @RequestBody Employee employee)
Optional<Employee> optionalDbEmployee = employeeRepository.findByEmployeeId(employeeId);
if (optionalDbEmployee.isEmpty())
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
Employee dbEmployee = optionalDbEmployee.get();
dbEmployee.setFirstName(employee.getFirstName());
dbEmployee.setLastName(employee.getLastName());
dbEmployee.setExtension(employee.getExtension());
dbEmployee.setEmail(employee.getEmail());
dbEmployee.setOfficeCode(employee.getOfficeCode());
dbEmployee.setReportsTo(employee.getReportsTo());
dbEmployee.setJobTitle(employee.getJobTitle());
return new ResponseEntity<>(HttpStatus.OK);
@DeleteMapping(path = "/deleteEmployee/employeeId")
public ResponseEntity<HttpStatus> deleteCustomer(@PathVariable("employeeId") int employeeId)
employeeRepository.deleteById(employeeId);
log.info("Employee with employee id Deleted successfully.", employeeId);
return new ResponseEntity<>(HttpStatus.OK);
Employee.java
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@Entity
@Table(name = "EMPLOYEE")
public class Employee
@Id
@Column(name = "EMPLOYEE_ID")
int employeeId;
@Column(name = "LAST_NAME")
String lastName;
@Column(name = "FIRST_NAME")
String firstName;
@Column(name = "EXTENSION")
String extension;
@Column(name = "EMAIL")
String email;
@Column(name = "OFFICE_CODE")
int officeCode;
@Column(name = "REPORTS_TO")
Integer reportsTo;
@Column(name = "JOB_TITLE")
String jobTitle;
OfficeResource.java
@RestController
@RequestMapping("/office")
@Slf4j
public class OfficeResource
@Autowired
OfficeRepository officeRepository;
@GetMapping(path = "/greetOffice", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello()
return "Hello Office !!!";
@GetMapping(path = "/getAllOffices", produces = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<List<Office>> getAllOffices()
List<Office> officeList = officeRepository.findAll();
return new ResponseEntity<>(officeList, HttpStatus.OK);
@GetMapping(path = "/getOffice/officeCode", produces = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Office> getOffice(@PathVariable("officeCode") int officeCode)
Optional<Office> optionalOffice = officeRepository.findByOfficeCode(officeCode);
if (optionalOffice.isEmpty())
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(optionalOffice.get(), HttpStatus.FOUND);
@PostMapping(path = "/createOffice", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<HttpStatus> createOffice(@RequestBody Office office)
Random random = new Random();
office.setOfficeCode(random.nextInt(999));
officeRepository.save(office);
log.info("Created office with office code : ", office.getOfficeCode());
return new ResponseEntity<>(HttpStatus.CREATED);
@PostMapping(path = "/createOffices", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> createOffices(@RequestBody List<Office> officeList)
int count = 0;
Random random = new Random();
for (Office office : officeList)
office.setOfficeCode(random.nextInt(999));
officeRepository.save(office);
log.info("Created office with office code : ", office.getOfficeCode());
count++;
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("countOfObjectCreated", String.valueOf(count));
return ResponseEntity.status(HttpStatus.CREATED).headers(responseHeaders).build();
@PutMapping(path = "/updateOffice/officeCode", consumes = MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<HttpStatus> updateOffice(@PathVariable("officeCode") int officeCode, @RequestBody Office office)
Optional<Office> optionalDbOffice = officeRepository.findByOfficeCode(officeCode);
if (optionalDbOffice.isEmpty())
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
Office dbOffice = optionalDbOffice.get();
dbOffice.setCity(office.getCity());
dbOffice.setPhone(office.getPhone());
dbOffice.setAddressLine1(office.getAddressLine1());
dbOffice.setAddressLine2(office.getAddressLine2());
dbOffice.setState(office.getState());
dbOffice.setCountry(office.getCountry());
dbOffice.setPostalCode(office.getPostalCode());
dbOffice.setTerritory(office.getTerritory());
return new ResponseEntity<>(HttpStatus.OK);
@DeleteMapping(path = "/deleteOffice/officeCode")
public ResponseEntity<HttpStatus> deleteOffice(@PathVariable("officeCode") int officeCode)
officeRepository.deleteById(officeCode);
log.info("Office with office code Deleted successfully.", officeCode);
return new ResponseEntity<>(HttpStatus.OK);
Office.java
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@Entity
@Table(name = "OFFICE")
public class Office
@Id
@Column(name = "OFFICE_CODE")
int officeCode;
@Column(name = "CITY")
String city;
@Column(name = "PHONE")
String phone;
@Column(name = "ADDRESS_LINE1")
String addressLine1;
@Column(name = "ADDRESS_LINE2")
String addressLine2;
@Column(name = "STATE")
String state;
@Column(name = "COUNTRY")
String country;
@Column(name = "POSTAL_CODE")
String postalCode;
@Column(name = "TERRITORY")
String territory;
SecurityConfiguration.java
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username,password,enabled from users where username = ?")
.authoritiesByUsernameQuery("select username,authority from authorities where username = ?")
.passwordEncoder(NoOpPasswordEncoder.getInstance());
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers("/employee/createEmployee", "/employee/createEmployees", "/employee/updateEmployee/**", "/employee/deleteEmployee/**").hasRole("Admin")
.antMatchers("/office/createOffice", "/office/createOffices", "/office/updateOffice/**", "/office/deleteOffice/**").hasRole("Admin")
.antMatchers("/employee/getEmployee/**", "/employee/getAllEmployees").hasAnyRole("Admin","User")
.antMatchers("/office/getOffice/**", "/office/getAllOffices").hasAnyRole("Admin","User")
.and().formLogin();
从浏览器中点击 url“http://localhost:8085/employee/getEmployee/1002”后,我得到了登录表单,在输入“Admin”用户“User1”的凭据后,得到“Forbidden”, status=403" 错误。
需要帮助。
【问题讨论】:
【参考方案1】:hasRole
和 hasAnyRole
在您的字符串前面加上 ROLE_
。请改用hasAuthoritiy
或hasAnyAuthority
。见spring docs
【讨论】:
进行更改后,我可以使用“User1”和“User2”成功访问任何需要“Admin”或“User”权限的端点。但是在访问任何只需要“Admin”权限的端点时,“User1”被配置为具有“Admin”权限;我收到“禁止,状态=403”错误。以上是关于Spring Boot中的Spring安全配置未按预期工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章
漫谈Spring Security 在Spring Boot 2.x endpoints中的应用