2015-10-20 20 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瞭解更多信息。