2015-10-20 18 views
0

我在Spring 4.2.0中创建了自定义login formcreate new account表单。它们工作正常。但是现在我已经为新创建的用户实现了自动登录,并成功登录创建的用户。但是,如果我注销并尝试使用相同凭据再次登录,则认证失败。并且验证也不适用于其他用户。所以用户能够登录的唯一时间是创建时间。认证失败后。让我觉得自动登录代码出于某种原因打破了春季登录认证。看看下面的代码。任何猜测为什么会发生?为新创建的用户添加自动登录失败登录表单身份验证

登录表单:

<form:form modelAttribute="loginForm" action="${pageContext.request.contextPath}/login" method="POST"> 
      Username:<form:input path="username" size="30" /> 
      Password:<form:password path="password" size="30" /> 
      <input type="submit" value="Login" /> 
</form:form> 

secuirty配置:

user.setPassword(passwordEncoder.encode(newAccountDetails.getPassword())); 
在用户后控制器

自动登录成功创建:

插入数据库之前

<security:http auto-config="true" use-expressions="true"> 
    <security:form-login default-target-url="/home" login-page="/" 
     authentication-failure-url="/?error=true" /> 
    <security:intercept-url pattern="/" access="permitAll" /> 
    <security:intercept-url pattern="/newaccount" 
     access="permitAll" /> 
     <security:intercept-url pattern="/createAccount/**" 
     access="isAnonymous()" /> 
     <security:intercept-url pattern="/login" 
     access="permitAll" /> 
     <security:intercept-url pattern="/logout" 
     access="permitAll" /> 
    <security:intercept-url pattern="/home" 
     access="isAuthenticated()" /> 
    <security:intercept-url pattern="/**" access="denyAll" /> 
    <security:csrf disabled="true" /> 
    <security:logout /> 
</security:http> 

<security:authentication-manager id="authManager"> 
    <security:authentication-provider> 
     <security:jdbc-user-service data-source-ref="dataSource" /> 
     <security:password-encoder ref="passwordEncoder"></security:password-encoder> 
    </security:authentication-provider> 
</security:authentication-manager> 
<bean id="passwordEncoder" 
    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"> 
</bean> 

密码加密

@RequestMapping("/createAccount") 
public ModelAndView submitCreateAccount(@ModelAttribute("newAccount") NewAccountDetails newAccountDetails) { 
    System.out.println(newAccountDetails); 
    ModelAndView mv = new ModelAndView(); 
    if (userServices.createUserService(newAccountDetails)) { 

     System.out.println("user created successfully"); 
     try { 
      userDetails = userDetailService.loadUserByUsername(newAccountDetails.getUsername()); 
      System.out.println(userDetails); 
      UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, 
        newAccountDetails.getPassword(), userDetails.getAuthorities()); 
      authManager.authenticate(authToken); 
      if (authToken.isAuthenticated()) { 
       System.out.println("New User is authenticated"); 
       SecurityContextHolder.getContext().setAuthentication(authToken); 
       mv.setViewName("redirect:/home"); 
      } else { 
       System.out.println("user not authenticated."); 
       mv.setViewName("redirect:/"); 
      } 
     } catch (Exception e) { 
      System.err.println("e: " + e); 
      mv.setViewName("redirect:/"); 
     } 
    } else { 
     System.out.println("user not created"); 
     mv.setViewName("redirect:/newaccount"); 
    } 
    return mv; 
} 
+0

你使用完全相同的编码器吗?如果你加载配置两次,你最终加载豆2次,你会得到不同的编码器。 –

+0

@ M.Deinum是的我正在使用相同的编码器。在安全配置中,我已经声明了在验证提供程序中用作密码编码器的'BCryptPasswordEncoder'类型的PasswordEncoder。并且在插入数据库之前对用户密码进行编码,使用相同的'PasswordEncoder'。所以我认为情况并非如此。你能解释一下配置加载两次的情况吗?我会检查我的代码。 –

+0

如果你同时在'ContextLoaderListener'和'DispatcherServlet'中加载配置,你会得到2个不同的编码器实例。另一件事是你创建一个身份验证管理器,给它一个ID,但不要将它连接到Spring Security。 –

回答

0

您使用特定的id定义了自己的AuthenticationManager。然而,Spring Security对这个特定的实例一无所知,并仍然使用默认的authenticationManager。因此,对于注册和登录,您基本上使用了AuthenticationManager的2个不同实例。

要解决此问题,您需要告诉Spring Security要使用哪一个,通过将authentication-manager-ref属性添加到主要http元素来执行此操作。

<security:http auto-config="true" use-expressions="true" authentication-manager-ref="<your-authetnication-manager-id>"> 

或者在您自己的AuthenticationManager specifing的alias

<security:authentication-manager id="authManager" alias="authenticationManager "> 

查看http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#ns-auth-manager了解更多信息。