【发布时间】:2015-06-19 01:52:54
【问题描述】:
我遇到了自定义 UserDetailService 和循环引用的问题。
一旦我向我的客户存储库添加@PreAuthorize 注释,我就会收到循环引用错误。很明显,这必须发生,因为UserDetailService 也使用它。所以我的问题是如何解决循环引用?我正在使用 spring-data-rest 和 spring-security。
下面的代码应该说明重现错误所需的一切
package demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class SpringTestApplication implements CommandLineRunner{
@Autowired
private CustomerRepository customerRepository;
public static void main(String[] args) {
SpringApplication.run(SpringTestApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Customer admin = customerRepository.save(new Customer("Demo", "1234"));
}
}
package demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.WebSecurityConfigurerAdapter;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Autowired
private DemoUserDetailService demoUserDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(demoUserDetailService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
http.csrf().disable();
}
}
package demo;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class DemoUserDetailService implements UserDetailsService {
private final CustomerRepository customerRepository;
@Autowired
public DemoUserDetailService(CustomerRepository customerRepository){
this.customerRepository = customerRepository;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
Customer customer = customerRepository.findByUsername(username).get();
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(
customer.getUsername(),
customer.getPassword(),
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"))
);
}
}
package demo;
import java.util.Optional;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.security.access.prepost.PreAuthorize;
public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long>{
@PreAuthorize("hasRole('ROLE_ADMIN')")
Optional<Customer> findByUsername(String username);
}
package demo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue
private long id;
private String username;
private String password;
public Customer(){}
public Customer(String username, String password){
this.username = username;
this.password = password;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
【问题讨论】:
标签: java spring jpa spring-security spring-data-rest