2015-05-30 16 views
18

Ricevo l'eccezione del cast di classe quando implemento la classe User di spring security. Voglio aggiungere alcuni dettagli aggiuntivi in ​​MyUserDetails (id) ma non riesco a ottenere il risultato.org.springframework.security.core.userdetails.User non può essere trasmesso a MyUserDetails

Questa domanda è risposta here ma poi due sto ricevendo errore, non so dove mi manca.

Qui di seguito è il mio codice:

SecurityConfig.java:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    @Qualifier("authenticationProvider") 
    AuthenticationProvider authenticationProvider; 

    @Autowired 
    DataSource dataSource; 

    @Autowired 
    public void configAuthentication(AuthenticationManagerBuilder auth) 
      throws Exception { 

     auth.jdbcAuthentication() 
       .dataSource(dataSource) 
       .passwordEncoder(passwordEncoder()) 
       .usersByUsernameQuery(
         "select username,password, enabled from users where username=?") 
       .authoritiesByUsernameQuery(
         "select username, role from user_roles where username=?"); 

    } 

    @Bean 
    public PasswordEncoder passwordEncoder() { 
     PasswordEncoder encoder = new BCryptPasswordEncoder(); 
     return encoder; 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 

     http.headers().cacheControl().and().xssProtection().and() 
       .frameOptions().and(); 

     http.authorizeRequests() 
       .antMatchers("/sadmin/**") 
       .access("hasRole('ROLE_SADMIN')") 
       .antMatchers("/admin/**") 
       .access("hasRole('ROLE_ADMIN') or hasRole('ROLE_SADMIN')") 
       .antMatchers("/") 
       .access("hasRole('ROLE_ADMIN') or hasRole('ROLE_SADMIN') or hasRole('ROLE_USER')") 
       .and().formLogin() 
       .loginProcessingUrl("/j_spring_security_check") 
       .loginPage("/login").failureUrl("/login?error") 
       .usernameParameter("username").passwordParameter("password") 
       .and().logout().logoutUrl("/j_spring_security_logout") 
       .logoutSuccessUrl("/login?logout").and().exceptionHandling() 
       .accessDeniedPage("/403").and().csrf(); 

     // session management URL for reference 
     // https://github.com/spring-projects/spring-security-javaconfig/blob/master/spring-security-javaconfig/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy 
    } 

MyUserDetails.java:

public class MyUserDetails extends User { 
    private int id; 

    public MyUserDetails(String username, String password, boolean enabled, 
      boolean accountNonExpired, boolean credentialsNonExpired, 
      boolean accountNonLocked, 
      Collection<? extends GrantedAuthority> authorities) { 
     super(username, password, enabled, accountNonExpired, 
       credentialsNonExpired, accountNonLocked, authorities); 

    } 
    // getter setter .... 
} 

CustomUserDetailsService.java:

@Service("userDetailsService") 
public class CustomUserDetailsService extends JdbcDaoImpl{ 
    @Override 
    protected List<UserDetails> loadUsersByUsername(String username) { 
     return getJdbcTemplate().query(super.getUsersByUsernameQuery(), new String[] { username }, 
       new RowMapper<UserDetails>() { 
        public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException { 
         String username = rs.getString("username"); 
         String password = rs.getString("password"); 
         boolean enabled = rs.getBoolean("enabled"); 
         boolean accountNonExpired = rs.getBoolean("accountNonExpired"); 
         boolean credentialsNonExpired = rs.getBoolean("credentialsNonExpired"); 
         boolean accountNonLocked = rs.getBoolean("accountNonLocked"); 
         int id = rs.getInt("id"); 

         MyUserDetails myUserDetails = new MyUserDetails(username, password, enabled, accountNonExpired, credentialsNonExpired, 
           accountNonLocked, AuthorityUtils.NO_AUTHORITIES); 

         myUserDetails.setId(id); 
         return myUserDetails; 
        } 

       }); 
    } 

    @Override 
    protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, 
      List<GrantedAuthority> combinedAuthorities) { 
     String returnUsername = userFromUserQuery.getUsername(); 

     if (!isUsernameBasedPrimaryKey()) { 
      returnUsername = username; 
     } 

     final MyUserDetails myUserDetails = new MyUserDetails(returnUsername, userFromUserQuery.getPassword(), userFromUserQuery.isEnabled(), 
       userFromUserQuery.isAccountNonExpired(), userFromUserQuery.isCredentialsNonExpired(), 
       userFromUserQuery.isAccountNonLocked(), combinedAuthorities); 

     myUserDetails.setId(((MyUserDetails) userFromUserQuery).getId()); 
     return myUserDetails; 
    } 
} 

codice per ottenere MyUserDetails:

MyUserDetails userDetails = (MyUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 

pom.xml:

<org.springframework.version>4.0.5.RELEASE</org.springframework.version> 
<spring.security.version>4.0.1.RELEASE</spring.security.version> 

StackTrace:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/housing] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to com.esociety.dto.MyUserDetails] with root cause 
java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to com.esociety.dto.MyUserDetails 
    at com.esociety.controller.LoginController.dashboard(LoginController.java:38) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:618) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:96) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655) 
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Unknown Source) 
+1

Quale versione di primavera si fa uso? Che stacktrace ottieni? Qual è la tua configurazione XML/Java per Spring Security? – Xaerxess

+0

@Xaerxess Ho aggiunto la versione di primavera e stacktrace e sto usando la configurazione di Java. ' 4.0.5.RELEASE 4.0.1.RELEASE' – pise

risposta

4

Ho "requisiti" simili come te e per me funziona bene. La mia configurazione è la seguente

@Configuration 
protected static class AuthenticationConfiguration extends 
     GlobalAuthenticationConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 
    @Autowired 
    private PasswordEncoder passwordEncoder; 

    @Override 
    public void init(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService).passwordEncoder(
       passwordEncoder); 
    } 

} 

La mia ipotesi è che il problema è con auth.jdbcAuthentication() in quanto fornirà attuazione UserDetailsService che restituisce la sicurezza di base User e non utilizza l'implementazione a tutti. Vedi javadoc:

aggiungere l'autenticazione JDBC al AuthenticationManagerBuilder e tornare un JdbcUserDetailsManagerConfigurer per consentire la personalizzazione del dell'autenticazione JDBC . Questo metodo garantisce inoltre che UserDetailsService sia disponibile per il metodo getDefaultUserDetailsService(). Notare che UserDetailsService aggiuntivo può sovrascrivere questo UserDetailsService come predefinito.

+0

Potete aiutarmi per favore con codice per 'Aggiungere l'autenticazione JDBC a AuthenticationManagerBuilder e restituire un JdbcUserDetailsManagerConfigurer per consentire la personalizzazione dell'autenticazione JDBC' e inoltre devo creare la classe AuthenticationConfiguration? – pise

+0

viene da javadoc (è citato) e dovrebbe solo spiegare perché la tua soluzione potrebbe non funzionare. il mio suggerimento è di usare 'auth.userDetailsService (userDetailsService) .passwordEncoder (passwordEncoder)' invece del tuo 'auth.jdbcAuthentication()' – sodik

+0

Grazie mille per il tuo suggerimento ha funzionato per me e sto postando il codice completo se nel caso qualcuno di fronte lo stesso problema sarebbe facile per lui. – pise

3

Ho seguito un'esercitazione in mkyong per aggiungere ulteriori dati in MyUserDetails (Nel mio caso ID e-mail). Si prega di fare riferimento a questo link per il codice completo, sto inserendo solo il codice in cui sono state apportate modifiche per ottenere l'ID e-mail.

Grazie a tutti per il vostro tempo e impegno. User Class

@Entity 
@Table(name = "users", catalog = "test") 
public class User { 

private String username; 
private String password; 
private boolean enabled; 
private boolean accountNonExpired; 
private boolean accountNonLocked; 
private boolean credentialsNonExpired; 
private String emailId; 

private Set<UserRole> userRole = new HashSet<UserRole>(0); 

public User() { 
} 

public User(String username, String password, boolean enabled,boolean accountNonExpired,boolean accountNonLocked,boolean credentialsNonExpired, String emailId) { 
    this.username = username; 
    this.password = password; 
    this.enabled = enabled; 
    this.accountNonExpired = accountNonExpired; 
    this.accountNonLocked = accountNonLocked; 
    this.credentialsNonExpired = credentialsNonExpired; 
    this.emailId = emailId; 
} 

public User(String username, String password, boolean enabled,boolean accountNonExpired,boolean accountNonLocked,boolean credentialsNonExpired, Set<UserRole> userRole,String emailId) { 
    this.username = username; 
    this.password = password; 
    this.enabled = enabled; 
    this.accountNonExpired = accountNonExpired; 
    this.accountNonLocked = accountNonLocked; 
    this.credentialsNonExpired = credentialsNonExpired; 
    this.emailId = emailId; 
    this.userRole = userRole; 
} 

@Id 
@Column(name = "username", unique = true, nullable = false, length = 45) 
public String getUsername() { 
    return this.username; 
} 

public void setUsername(String username) { 
    this.username = username; 
} 

@Column(name = "password", nullable = false, length = 60) 
public String getPassword() { 
    return this.password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

@Column(name = "enabled", nullable = false) 
public boolean isEnabled() { 
    return this.enabled; 
} 

public void setEnabled(boolean enabled) { 
    this.enabled = enabled; 
} 


@Column(name = "accountNonExpired", nullable = false) 
public boolean isAccountNonExpired() { 
    return accountNonExpired; 
} 

public void setAccountNonExpired(boolean accountNonExpired) { 
    this.accountNonExpired = accountNonExpired; 
} 

@Column(name = "accountNonLocked", nullable = false) 
public boolean isAccountNonLocked() { 
    return accountNonLocked; 
} 

public void setAccountNonLocked(boolean accountNonLocked) { 
    this.accountNonLocked = accountNonLocked; 
} 

@Column(name = "credentialsNonExpired", nullable = false) 
public boolean isCredentialsNonExpired() { 
    return credentialsNonExpired; 
} 

public void setCredentialsNonExpired(boolean credentialsNonExpired) { 
    this.credentialsNonExpired = credentialsNonExpired; 
} 

@Column(name = "emailId", nullable = false) 
public String getEmailId() { 
    return emailId; 
} 

public void setEmailId(String emailId) { 
    this.emailId = emailId; 
} 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user") 
public Set<UserRole> getUserRole() { 
    return this.userRole; 
} 

public void setUserRole(Set<UserRole> userRole) { 
    this.userRole = userRole; 
} 

} 

MyUserDetails Classe

public class MyUserDetails extends User { 

private final String emailId; 

public MyUserDetails(String username, String password, boolean enabled, 
     boolean accountNonExpired, boolean credentialsNonExpired, 
     boolean accountNonLocked,String emailId, 
     Collection<? extends GrantedAuthority> authorities) { 
    super(username, password, enabled, accountNonExpired, 
      credentialsNonExpired, accountNonLocked, authorities); 
    // TODO Auto-generated constructor stub 
    this.emailId = emailId; 
} 

public String getEmailId() { 
    return emailId; 
} 

} 

MyUserDetailsService Classe

@Service("userDetailsService") 
public class MyUserDetailsService implements UserDetailsService { 

@Autowired 
private UserDao userDao; 

@Transactional(readOnly=true) 
@Override 
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { 

    com.mkyong.users.model.User user = userDao.findByUserName(username); 
    List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole()); 

    return buildUserForAuthentication(user, authorities); 

} 

private User buildUserForAuthentication(com.mkyong.users.model.User user, List<GrantedAuthority> authorities) { 
    MyUserDetails myUserDetails = new MyUserDetails (user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isCredentialsNonExpired(), user.getEmailId(),authorities); 
    return myUserDetails; 
} 

private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) { 

    Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>(); 

    // Build user's authorities 
    for (UserRole userRole : userRoles) { 
     setAuths.add(new SimpleGrantedAuthority(userRole.getRole())); 
    } 

    List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths); 

    return Result; 
} 

} 

classe Config sicurezza non v'è alcun cambiamento in questo. Questo è esattamente uguale a collegamento tutorial, ma questo era suggerimento dato dal @sodik per cambiare JDBCAuthentication

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

@Autowired 
@Qualifier("userDetailsService") 
UserDetailsService userDetailsService; 

@Autowired 
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 

    http.authorizeRequests().antMatchers("/admin/**") 
     .access("hasRole('ROLE_ADMIN')").and().formLogin() 
     .loginPage("/login").failureUrl("/login?error") 
      .usernameParameter("username") 
      .passwordParameter("password") 
      .and().logout().logoutSuccessUrl("/login?logout") 
      .and().csrf() 
      .and().exceptionHandling().accessDeniedPage("/403"); 
} 

@Bean 
public PasswordEncoder passwordEncoder(){ 
    PasswordEncoder encoder = new BCryptPasswordEncoder(); 
    return encoder; 
} 

} 

AppConfig l'aggiunta di password in questo perché la password non è stata impostata in collegamento esercitazione

@EnableWebMvc 
@Configuration 
@ComponentScan({ "com.mkyong.*" }) 
@EnableTransactionManagement 
@Import({ SecurityConfig.class }) 
public class AppConfig { 
    @Bean(name = "dataSource") 
    public BasicDataSource dataSource() { 

     BasicDataSource ds = new BasicDataSource(); 
     ds.setDriverClassName("com.mysql.jdbc.Driver"); 
     ds.setUrl("jdbc:mysql://localhost:3036/test"); 
     ds.setUsername("root"); 
     ds.setPassword("password"); 
     return ds; 
    } 
} 
Problemi correlati