Приложение Spring Boot имеет пользовательские UserDetails. Все работает правильно, когда все приложение выполняет аутентификацию существующих пользователей из базы данных с классом User. Однако возникают проблемы, когда я пытаюсь внести изменения, чтобы люди могли создавать новые учетные записи пользователей через графический интерфейс приложения. В частности, изменение пользовательского UserDetailsService
, чтобы стать UserDetailsManager
, необходимо изменить класс User
на явно implement UserDetails
, что, в свою очередь, приводит к тому, что Spring не сможет скомпилировать банку, когда я ввожу java -jar target/modular-0.0.1-SNAPSHOT.jar
в терминал из корневого каталога приложения.Невозможно автоподписать пользовательские UserDetails
Сообщение об ошибке ядро:
java.lang.IllegalArgumentException:
Not an managed type: interface org.springframework.security.core.userdetails.UserDetails
Какие конкретные изменения должны быть внесены в код ниже, для того, чтобы дать возможность Spring, чтобы иметь возможность скомпилировать приложение с обычаем UserDetails
и UserDetailsManager
?
Вот код для базового класса в приложение, которое включает в себя конфигурацию Spring Security:
@SpringBootApplication
@Controller
@EnableJpaRepositories(basePackages = "demo", considerNestedRepositories = true)
public class UiApplication extends WebMvcConfigurerAdapter {
@Autowired
private WebLeadRepository myrepo;
@Autowired
private Users users;//duplicate from AuthenticationSecurity internal class below. Remove one?
// Match everything without a suffix (so not a static resource)
@RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
// Forward to home page so that route is preserved.
return "forward:/";
}
@RequestMapping("/user")
@ResponseBody
public Principal user(Principal user) {
return user;
}
//lots of other @RequestMapping @ResponseBody url handling methods
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private Users users;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(users);
}
}
@SuppressWarnings("deprecation")
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests()
.antMatchers("/sign-up").permitAll()
.antMatchers("/index.html", "/", "/login", "/something*")
.permitAll().anyRequest().authenticated().and().csrf()
.csrfTokenRepository(csrfTokenRepository()).and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
@Repository//This repository is what Spring cannot seem to create in the stack trace
interface UserRepository extends CrudRepository<UserDetails, Long> {
User findByName(String name);
}
}
Users.java
является:
@Service
class Users implements UserDetailsManager {
private UserRepository repo;
@Autowired
public Users(UserRepository repo) {this.repo = repo;}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = repo.findByName(username);
if (user == null) {throw new UsernameNotFoundException("Username was not found. ");}
List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("admin")) {auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN");}
String password = user.getPassword();
return new org.springframework.security.core.userdetails.User(username, password, auth);
}
@Override
public void createUser(UserDetails user) {// TODO Auto-generated method stub
repo.save(user);
}
@Override
public void updateUser(UserDetails user) {// TODO Auto-generated method stub
repo.save(user);
}
@Override
public void deleteUser(String username) {// TODO Auto-generated method stub
User deluser = (User)this.loadUserByUsername(username);
repo.delete(deluser);
}
@Override
public void changePassword(String oldPassword, String newPassword) {
// TODO Auto-generated method stub
}
@Override
public boolean userExists(String username) {
// TODO Auto-generated method stub
return false;
}
}
И User.java
является:
@Entity
class User implements UserDetails{
@GeneratedValue
@Id
private Long iduser;
private String name;//valid email address only
private String password;
//lots of other properties that model all the things the User does in the app
//getters and setters
public String getName() {return name;}//valid email address
public void setName(String name) {this.name = name;}//valid email address
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
//LOTS OF OTHER GETTERS AND SETTERS OMITTED HERE, THAT MANAGE MANY CUSTOM PROPERTIES
// Also, All the following are for implementing UserDetails
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAccountNonExpired() {// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAccountNonLocked() {// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCredentialsNonExpired() {// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnabled() {// TODO Auto-generated method stub
return false;
}
}
WebLeadRepository.java
:
public interface WebLeadRepository extends JpaRepository<WebLead, Long> {
List<WebLead> findByLastname(String lastName);
List<WebLead> findBySessionid(String sid);
WebLead findByIdlead(Long idl);
}
Полная трассировка стека слишком длинная для этой публикации, но I have uploaded the complete stack trace to a file sharing site, which you can view by clicking on this link. Кроме того, основная причина в трассировке стека приведены ниже следующим образом:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uiApplication.UserRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: interface org.springframework.security.core.userdetails.UserDetails
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 38 more
Caused by: java.lang.IllegalArgumentException: Not an managed type: interface org.springframework.security.core.userdetails.UserDetails
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:219)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:67)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:152)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:99)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:81)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:185)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
Ваш репозиторий нуждается в 'User', а не' UserDetails' в объявлении типа. Измените 'CrudRepository' на 'CrudRepository '. –
В ваших пользовательских реализациях 'UserDetailsManager' вам нужно передать' UserDetails' в объект 'User'. –
@ M.Deinum Ваши комментарии предоставили ответ. Если вы хотите написать их в качестве ответа, я был бы рад отметить его как принятый и +1. В частности, решение включало в себя создание объектов различных методов назад и вперед между «User» и «UserDetails», чтобы CrudRepository работал с экземплярами «User» с источником данных, а также позволял Spring Security работать с объектами UserDetails , – CodeMed