这个问题已经有答案了:
Spring Boot circular reference is already handled in application.properties but seems ignored by Java Spring Boot executable jar file(1个答案)
2个月前关闭。
因此我使用Java Sping Boot 创建了这个简单登录系统应用程序,并使用Spring Security进行身份验证。
这是应用程序的规范:
- Spring工具套件4.18.0.RELEASE
- Spring安全6
- 使用Java 17
- 构建在Linux ubuntu 22.04之上
- Thymeleaf
- 默认情况下,
application.properties
已位于SBTLEmpManSys/src/main/resources
中的resource
文件夹中 - 我使用STS(Spring工具套件)提供的Maven构建功能将这些作品打包成可执行的jar文件
当我想为SecurityConfiguration.java
使用WebSecurityConfigurerAdapter
时,IDE没有提供该选项。它提供了WebSecurityConfiguration
,所以我使用它。结果它给出了循环引用。
这是一个图表:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfiguration (field private org.springframework.security.config.annotation.web.builders.HttpSecurity org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.httpSecurity)
↑ ↓
| org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]
└─────┘
我通过在application.properties
中设置spring.main.allow-circular-reference=true
作为临时解决方案来完成我的工作。但是这个问题会在可执行的.jar文件中重新出现
另一方面,我需要这个安全配置文件为我的服务实现文件EmpServiceImpl.java
提供BCryptPasswordEncoder
。
我试着在这里和那里使用@Lazy
,但没有效果。我也试着通过谷歌和这个论坛来解决这个问题,但仍然无法解决。
有人能帮忙吗?这真让我给予头疼。
这是我的文件。
这是安全配置
package com.kastamer.sbtl.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.PropertySource;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.kastamer.sbtl.service.EmpService;
@Configuration
@PropertySource(value = "classpath:application.properties")
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfiguration {
// public EmpService empService;
// @Lazy --> NO EFFECT
@Bean
public BCryptPasswordEncoder passwordEncoder() {
// TODO Auto-generated method stub
return new BCryptPasswordEncoder();
}
// @Lazy --> NO EFFECT
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
AuthenticationManagerBuilder authManBuild = http.getSharedObject(AuthenticationManagerBuilder.class);
http.authorizeHttpRequests((requests) -> requests.requestMatchers(
"/registrasi",
"/js**",
"/css**",
"/img**")
.permitAll().anyRequest().authenticated())
.formLogin((form) -> form.loginPage("/login").permitAll())
.logout((logout) -> logout.invalidateHttpSession(true).clearAuthentication(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout").permitAll());
return http.build();
}
}
以下是服务实现:
package com.kastamer.sbtl.service;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.kastamer.sbtl.model.EmpRole;
import com.kastamer.sbtl.model.Employee;
import com.kastamer.sbtl.repository.EmployeeRepository;
import com.kastamer.sbtl.web.dto.EmpRegistrationDTO;
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmployeeRepository empRepDAO;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
//@Autowired //THIS is ADDITION to AVOID CIRCULAR REFERENCE --> ANNOTATION NO EFFECT
//public EmpServiceImpl(@Lazy EmployeeRepository empRepDAO) { //ANNOTATION '@Lazy' is ADDITION to AVOID CIRCULAR REFERENCE --> ANNOTATION NO EFFECT
public EmpServiceImpl(EmployeeRepository empRepDAO) {
super();
this.empRepDAO = empRepDAO;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
Employee pegawai = empRepDAO.findByEmail(username);
if (pegawai == null) {
throw new UsernameNotFoundException("Email atau kata sandi tidak cocok!");
}
return new org.springframework.security.core.userdetails.User(pegawai.getEmail(), pegawai.getPassword(), mapRolesToAuthority(pegawai.getRoles())); //return null;
}
@Override
public Employee save(EmpRegistrationDTO empRegistrationDTO) {
// TODO Auto-generated method stub
Employee karyawan = new Employee(
empRegistrationDTO.getFullName(),
empRegistrationDTO.getEmail(),
passwordEncoder.encode(empRegistrationDTO.getPassword()),
Arrays.asList(new EmpRole("ROLE_USER")));
return empRepDAO.save(karyawan); //return null;
}
@Override
public void simpanPembaruanData(Employee employee) {
// TODO Auto-generated method stub
employee.setPassword(passwordEncoder.encode(employee.getPassword()));
this.empRepDAO.save(employee);
}
private Collection<? extends GrantedAuthority> mapRolesToAuthority(Collection<EmpRole> roles) {
// TODO Auto-generated method stub
return roles.stream().map(role -> new SimpleGrantedAuthority(role.getNamaRole())).collect(Collectors.toList());
}
//PART POJOK KARYAWAN
@Override
public List<Employee> getAllEmployees() {
// TODO Auto-generated method stub
return empRepDAO.findAll(); //return null;
}
@Override
public Employee getEmployeeById(long id) {
// TODO Auto-generated method stub
Optional<Employee> optEmp = empRepDAO.findById(id);
Employee empl = null;
if (optEmp.isPresent()) {
empl = optEmp.get();
} else {
throw new RuntimeException("Karyawan dengan emp_id '" + id + "' tidak bisa ditemukan");
}
return empl; //return null;
}
@Override
public void deleteEmployeeById(long id) {
// TODO Auto-generated method stub
this.empRepDAO.deleteById(id);
}
@Override
public Page<Employee> findPaginated(int pageNo, int pageSize, String sortField, String sortAscOrDesc) {
// TODO Auto-generated method stub
Sort runut = sortAscOrDesc.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortField).ascending() : Sort.by(sortField).descending();
Pageable pageable = PageRequest.of(pageNo - 1, pageSize, runut);
return this.empRepDAO.findAll(pageable); //return null;
}
}
这是application.properties
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:postgresql://localhost:5432/myDB
spring.datasource.username=[POSTGRES_LOGIN]
spring.datasource.password=[POSTGRES_PASSWORD]
spring.datasource.driver-class-name=org.postgresql.Driver
# The PostgreSQL dialect makes Hibernate generate better Postgresql for the chosen databse
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
# Hibernate ddl auto (create, create-drop, validate, update, none --> 'default')
spring.jpa.hibernate.ddl-auto=update
# Prepare logging-time system for Spring-Boot engine & will print logs in console (also work as work-level to monitor generated HQL in console)
logging.level.org.hibernate.sql=debug
logging.level.org.hibernate.type=trace
#spring.jpa.show-sql=true
# Default user login and password for spring security web login page (if spring security is enabled)
#spring.security.user.name=spring
#spring.security.user.password=spring123
#spring.security.user.roles=USER
spring.main.allow-bean-definition-overriding=true
#spring.main.allow-circular-references=true
1条答案
按热度按时间lymnna711#
您可以通过将密码编码器的工厂方法设置为静态来打破这种循环:
这样,密码编码器的创建就不再依赖于被示例化的配置类的示例。