当前位置: 首页 > 知识库问答 >
问题:

如何修复UserDetails实现的ClassCastException?

段晨
2023-03-14
@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    public Storages storage;

    @Override
    public LoggedUser loadUserByUsername(String email)
        throws UsernameNotFoundException {

    boolean enabled = true;
    boolean accountNonExpired = true;
    boolean credentialsNonExpired = true;
    boolean accountNonLocked = true;

    milkiv.easyword.models.User user = getUserDetails(email);
    if (user != null) {
        LoggedUser userdetails = new LoggedUser(
            user,
            enabled,
            accountNonExpired,
            credentialsNonExpired,
            accountNonLocked,
            getAuthorities(1)
        );
        return userdetails;
    } else {
        throw new UsernameNotFoundException(email);
    }
    }

    public List<GrantedAuthority> getAuthorities(int role) {

    List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
    if (role == 1) {
        authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    } else if (role == 2) {
        authList.add(new SimpleGrantedAuthority("ROLE_USER"));
    }
    return authList;
    }

    private milkiv.easyword.models.User getUserDetails(String email) {
    milkiv.easyword.models.User user = storage.uSM.findByEmail(email);
    return user;
    }
    }
public class LoggedUser implements UserDetails{

    User user = new User();
    private boolean enabled;
    private boolean accountNonExpired;
    private boolean credentialsNonExpired;
    private boolean accountNonLocked;
    private Collection<? extends GrantedAuthority> authorities;

    public LoggedUser() {
    }

    public LoggedUser(User user, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
    setUser(user);
    this.enabled=enabled;
    this.accountNonExpired=accountNonExpired;
    this.credentialsNonExpired=credentialsNonExpired;
    this.accountNonLocked=accountNonLocked;
    this.authorities=authorities;
    }

    public void setUser(User user) {
    this.user = user;

    }

    private User getUser() {
    return this.user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
    return this.authorities;
    }

    @Override
    public String getPassword() {
    return this.user.getPassword();
    }

    @Override
    public String getUsername() {
    return this.user.getNickname();
    }

    @Override
    public boolean isAccountNonExpired() {
    return this.accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
    return this.accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
    return this.credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
    return this.enabled;
    }

    public String getEmail(){
    return this.user.getEmail();
    }

    public int getId(){
    return this.user.getUserId();
    }

    public Date getRegistrationDate(){
    return this.user.getRegistrationDate();
    }
}
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://www.springframework.org/schema/security"
         xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security 
http://www.springframework.org/schema/security/spring-security.xsd">

    <http auto-config="true" use-expressions="true">
    <intercept-url pattern="/sign/in" access="isAnonymous()" /> 
    <intercept-url pattern="/sign/up" access="isAnonymous()" /> 
    <intercept-url pattern="/secret/page" access="isAuthenticated()" />
    <intercept-url pattern="/sign/out" access="isAuthenticated()" />
    <intercept-url pattern="/user/myinfo" access="isAuthenticated()" />

    <form-login
        login-page="/sign/in"
        default-target-url="/secret/page"
        authentication-failure-url="/sign/in?failed=1"
        password-parameter="password"
        username-parameter="email"
    />
    <csrf disabled="true"/>
    <logout
        logout-url="/sign/out"
    />  
    </http>

    <authentication-manager erase-credentials="false">
    <authentication-provider user-service-ref="customUserDetailsService">

    </authentication-provider>
    </authentication-manager>

    <beans:bean id="customUserDetailsService" class="milkiv.easyword.controller.sign.CustomUserDetailsService"/>
</beans:beans>
    @RequestMapping(method = RequestMethod.POST, path = "/user/changepassword")
        public String changePassword(@Valid @ModelAttribute("userPasswordChange") final UserPasswordChange userPasswordChange, BindingResult bindingResult, ModelMap model) {
        if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserDetails){
            //PRINTED
            System.out.println("UserDetails +");
        }
        if(SecurityContextHolder.getContext().getAuthentication().getPrincipal().getClass()==LoggedUser.class){
            //NOT PRINTED
            System.out.println("LoggedUser +");
        }
        try {
            LoggedUser ud = (LoggedUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        } catch (Exception ex) {
            //PRINTED
            System.out.println("LoggedUser -");
        }
        //class org.springframework.security.core.userdetails.User
System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal().getClass());
    return "user/myInfo";
        }
testChangeUserPassword(milkiv.easyword.controller.sign.UserTest)  Time elapsed: 0.896 sec  <<< ERROR!
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to milkiv.easyword.controller.sign.LoggedUser
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    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:169)
    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.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    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.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.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.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.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    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.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:156)
    at milkiv.easyword.controller.sign.UserTest.testChangeUserPassword(UserTest.java:69)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:85)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:86)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:241)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:242)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:137)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to milkiv.easyword.controller.sign.LoggedUser
    at milkiv.easyword.controller.User.changePassword(User.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    ... 77 more


Results :

Tests in error: 
  testChangeUserPassword(milkiv.easyword.controller.sign.UserTest): Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to milkiv.easyword.controller.sign.LoggedUser

编辑:测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:resources/spring-context.xml", "classpath:resources/spring-security.xml"})
@WebAppConfiguration
public class UserTest {

    MockMvc mockMvc;

    Storages storages;

    @Autowired
    private Filter springSecurityFilterChain;

    @Autowired
    WebApplicationContext wac; // cached

    @Before
    public void doBeforeTests() {
    mockMvc = MockMvcBuilders
        .webAppContextSetup(wac)
        .addFilters(springSecurityFilterChain)
        .build();
    ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring-context.xml", "resources/spring-security.xml");
    storages = context.getBean(Storages.class);
    }

    @Test
    public void testChangeUserPassword() throws Exception {
    mockMvc.perform(post("/user/changepassword").with(user("test@mail.com").password("test"))
    )
        .andExpect(status().isOk());
    }
}

共有1个答案

蓬运诚
2023-03-14

而不是这样:

user("test@mail.com").password("test")

使用:

user(userDetails)

其中UserDetailsLoggedUser类的实例。

 类似资料:
  • 我的应用程序在Google Play中被拒绝了,因为TrustManager的一些不安全的实现。 但是在我的库中,我只有TrustManager的一个实现(这是我的SSLUtil类)。 我不明白为什么我的申请被拒绝了。

  • 我试图将一些示例代码迁移到Kotlin。 目前,我想将Spring Data Mongo示例转换为Kotlin。有一个,原始数据Mongo版本看起来是: 接口包括一些getXXX和isXXX方法,如何将添加到Kotlin中的和proerpties? 新的问题是当使用销毁,它不工作。 位于https://github.com/hantsy/spring-active-sample/blob/mast

  • 这是二叉树实现的一个例子。这段代码工作正常。但是我可以在add方法中将根创建为单个一次性节点吗?

  • 问题内容: 运行RssReader的Android项目时出现错误。 码: 它显示以下错误: 如何解决此问题? 问题答案: 当应用程序尝试在其主线程上执行联网操作时,将引发此异常。在AsyncTask以下位置运行代码: 如何执行任务: 在MainActivity.java文件中,您可以在oncreate()方法中添加此行 不要忘记将其添加到AndroidManifest.xml文件中:

  • 问题内容: 应用程序通过使用jsf形式读取参数来发送字母。我不明白为什么以及如何解决它,因为当您在开发环境中运行时,一切正常。当我将应用程序放置在VPS服务器上时,会出现下一个错误堆栈(尽管该应用程序可以根据需要在本地主机上运行): 问题答案: 我创建并编译使用版本jdk_8u151和JRE的项目。那时,就像在服务器上一样,项目是在后来的jre下启动的。使用相同版本的jre解决了该问题。泰

  • 运行Java程序时,我收到一个错误。出了什么问题,我该怎么修复它?