1

J'ai une application configurée avec la sécurité de printemps.
Tout fonctionne aussi bien.
Le UserDetailService est:Injection de dépendances et sérialisation Objet au printemps

@Service(value = "userDetail") 
public class UserDetailServiceImpl implements UserDetailsService, Serializable { 
    private static final long serialVersionUID = 3487495895819392L; 

    @Autowired 
    private IUserDetailRepository iUserDetailRepository; 

    @Autowired 
    private IUserRoleRepository iUserRoleRepository; 

    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     User user = iUserDetailRepository.loadUserByUsername(username); 
     List<UserRole> roles = iUserRoleRepository.getAllRoleByUserName(username); 
     UserDetails u = new UserDetails() { 

      @Override 
      public boolean isEnabled() { 
       // return user.getEnable(); 
       return true; 
      } 

      @Override 
      public boolean isCredentialsNonExpired() { 
       return true; 
      } 

      @Override 
      public boolean isAccountNonLocked() { 
       return true; 
      } 

      @Override 
      public boolean isAccountNonExpired() { 
       return true; 
      } 

      @Override 
      public String getUsername() { 
       // return user.getUsername(); 
       return "reyhane"; 
      } 

      @Override 
      public String getPassword() { 
       // return user.getPassword(); 
       return "reyhane"; 
      } 

      @Override 
      public Collection<? extends GrantedAuthority> getAuthorities() { 
       Collection<GrantedAuthority> authorities = new ArrayList<>(); 
       SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ADMIN"); 
       authorities.add(authority); 

       return authorities; 

      } 
     }; 
     return u; 
    } 

} 

Après que je fus forcé de la session de printemps de configuration sur cette configuration pour enregistrer le contexte de la sécurité du ressort dans Redis.
Il existe un problème dans UserDetailService.
UserDetailService ont deux autowired déposées comme indiqué ci-dessus sont:

@Autowired 
private IUserDetailRepository iUserDetailRepository; 

@Autowired 
private IUserRoleRepository iUserRoleRepository; 

Ce champ deux autowired sont pour obtenir l'utilisateur et les informations des rôles de l'utilisateur de DB.
Il est intéressant ici que quand je commente ce deux autowired comme ceci:

//@Autowired 
private IUserDetailRepository iUserDetailRepository; 

//@Autowired 
private IUserRoleRepository iUserRoleRepository; 

et remplir manuellement la session role.Spring de l'utilisateur et l'utilisateur fonctionne aussi bien, mais quand cela deux @Autowired existent dans la classe l'exception ci-dessous soulevée:

causés par: org.springframework.core.serializer.support.SerializationFailedException: Impossible de sérialiser l'objet en utilisant DefaultSerializer; exception imbriquée est java.io.NotSerializableException: org.springframework.dao.support.PersistenceExceptionTranslationInterceptor à org.springframework.core.serializer.support.SerializingConverter.convert (SerializingConverter.java:68) ~ [printemps-core- 4.3.2.RELEASE.jar: 4.3.2.RELEASE] au org.springframework.core.serializer.support.SerializingConverter.convert (SerializingConverter.java:35) ~ [spring-core-4.3.2.RELEASE.jar : 4.3.2.RELEASE] à org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize (JdkSerializationRedisSerializer.java:90) ~ [spring-data-redis-1.7.2.RELEASE.jar: na] .. 35 images communes omises Causée par: java.io.NotSerializableException: org.springframework.dao.support.PersistenceExceptionTranslationInterceptor à java.io.ObjectOutputStream.writeObject0 (ObjectOutputStream.java:1184) ~ [na: 1.8.0_111] à java.io.ObjectOutputStream.defaultWriteFields (ObjectOutputStream.java: 1548) ~ [na: 1.8.0_111]

Tout le monde sait que se passe-t-il?
Je ne comprends pas ce qui se passe.
Je ne sais pas quelle est la clé pour la recherche dans google
Je veux savoir ce qui se passe entre la session de printemps et la sécurité de printemps et comment le résoudre.
Merci pour votre aide

+1

Le problème principal est que vous utilisez une classe interne anonyme dans votre méthode. Ne faites pas cela, construisez simplement un nouveau 'User' à la place d'un nouveau' UserDetails' et vous n'avez pas besoin de hacks. –

+0

S'il vous plaît pourriez-vous expliquer plus –

Répondre

2

Cela n'a en fait rien à voir avec ces dépendances, il est dû au fait que vous utilisez un (non static) classe interne. Vous devez utiliser une classe static intégrée ou simplement utiliser la classe User de Spring Security.(Plus de détails sur intérieure, (non) des classes intégrées statiques se trouvent dans this answer.

En bref en raison du fait de vous en utilisant une classe interne nécessite une instance de la classe externe d'exister. Et quand sérialisation le UserDetails il sera aussi essayer de sérialiser la classe externe.

la solution la plus simple consiste à réécrire votre code et utiliser la classe Spring Security fourni User (en supposant que vous utilisez la sécurité Spring 4.2, vous pouvez utiliser le UserBuilder).

@Override 
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
    User user = iUserDetailRepository.loadUserByUsername(username); 
    List<UserRole> roles = iUserRoleRepository.getAllRoleByUserName(username); 

    return User.withUsername(user.getUsername()) 
         .password(user.getPassword()) 
         .disabled(!user.getEnable()) 
         .roles(roles.stream().map(<convert-to-SimpleGrantedAuthority>).collect(Collectors.toList())) 
         .build(); 
} 

Si vous êtes au printemps Sécurité avant 4.2, vous pouvez simplement construire un objet User en utilisant le constructeur.

return new User(user.getUsername(), user.getPassword(), user.getEnable(), true, true, true, <convert-roles-to-SimpleGrantedAuthoritu>); 

Lorsque le retour d'une classe concrète, il ne nécessite pas une instance de la classe externe (comme il est une classe interne) et il ne sera pas essayer de sérialiser. Il ne sérialisera que le User et rien d'autre.

+0

Merci beaucoup pour votre meilleure réponse –

0

je résoudre mon problème avec cette solution:

private static IUserDetailRepository userDetailRepository; 

private static IUserRoleRepository userRoleRepository; 

    @Autowired 
    public void setUserDetailRepository(IUserDetailRepository userDetailRepository) { 
     UserDetailServiceImpl.userDetailRepository = userDetailRepository; 
    } 

    @Autowired 
    public void setUserRoleRepository(IUserRoleRepository userRoleRepository) { 
     UserDetailServiceImpl.userRoleRepository = userRoleRepository; 
    } 
+0

Voir le commentaire qui n'est pas vraiment une solution, mais un hack pour le faire fonctionner. –

+0

Avez-vous une solution pour cela? –

+0

Je vous l'ai déjà donné, n'utilisez pas une classe interne anonyme. Utilisez la sécurité de printemps 'User' et remplissez les propriétés en conséquence. –