2015-05-30 15 views
18

Ich erhalte eine Klassenübergabe-Ausnahme, wenn ich die Benutzerklasse der Federsicherheit implementiere. Ich möchte einige zusätzliche Details in MyUserDetails (id) hinzufügen, aber ich bin nicht in der Lage, das Ergebnis zu erhalten.org.springframework.security.core.userdetails.User kann nicht in "MyUserDetails" umgewandelt werden

Diese Frage wird beantwortet here aber dann zwei bekomme ich Fehler, weiß nicht, wo ich vermisse.

Unten ist mein Code:

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:

Code MyUserDetails zu erhalten:

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

Welche Version von Spring in Tutorial Link gesetzt wurde tun Sie benutzen? Welchen Stacktrace bekommst du? Wie lautet Ihre XML/Java-Konfiguration für Spring Security? – Xaerxess

+0

@Xaerxess Ich habe Spring Version und Stacktrace hinzugefügt und ich benutze Java Config. ' 4.0.5.RELEASE 4.0.1.RELEASE' – pise

Antwort

4

Ich habe ähnliche "Anforderungen" wie Sie und für mich funktioniert es gut. Mein Setup ist als

@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); 
    } 

} 

Meine Vermutung folgt, ist das Ihr Problem mit auth.jdbcAuthentication() ist, da es die Umsetzung von UserDetailsService bieten wird, die Kernsicherheit User zurück und verwendet nicht Ihre Implementierung überhaupt. Siehe javadoc:

In JDBC-Authentifizierung zum AuthenticationManagerBuilder und zurück eine JdbcUserDetailsManagerConfigurer Anpassung der JDBC Authentifizierung zu ermöglichen. Diese Methode stellt außerdem sicher, dass ein UserDetailsService für die getDefaultUserDetailsService() -Methode verfügbar ist. Beachten Sie, dass zusätzliche UserDetailsServices dieses UserDetailsService standardmäßig überschreiben können.

+0

Kannst du mir bitte helfen? Code für 'Fügen Sie dem AuthenticationManagerBuilder eine JDBC-Authentifizierung hinzu und geben Sie einen JdbcUserDetailsManagerConfigurer zurück, um die Anpassung der JDBC-Authentifizierung zu ermöglichen', und außerdem muss ich die AuthenticationConfiguration-Klasse erstellen? – pise

+0

das ist von javadoc (es wird zitiert) und es sollte nur erklären, warum Ihre Lösung nicht funktioniert. mein Vorschlag ist, 'auth.userDetailsService (userDetailsService) .passwordEncoder (passwordEncoder)' anstelle von 'auth.jdbcAuthentication()' – sodik

+0

zu verwenden Vielen Dank Ihr Tipp funktionierte für mich und ich poste vollen Code, wenn jemand ein gegenüberstellt das gleiche Problem wäre es leicht für ihn. – pise

3

Ich habe mkyong Tutorial genommen, um zusätzliche Daten in MyUserDetails (in meinem Fall E-Mail-ID) hinzuzufügen. Bitte beziehen Sie sich auf link für den vollständigen Code, ich setze nur den Code, den ich für die E-Mail-ID geändert habe.

Vielen Dank für Ihre Zeit und Mühe. Benutzerklasse

@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 Klasse

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 Klasse

@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; 
} 

} 

Security Config-Klasse gibt es keine Änderung in diesem. Das ist genau das gleiche wie Tutorial Link, aber das war von @sodik gegeben Hinweis 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 Hinzufügen Passwort in das zu ändern, weil das Kennwort nicht

@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; 
    } 
} 
Verwandte Themen