2013-03-11 30 views
0

我試圖使用自定義過濾器來實現Spring安全授權。Spring Security;定製過濾器和用戶服務引用不能一起工作

的security.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.1.xsd 
     http://www.springframework.org/schema/util 
     http://www.springframework.org/schema/util/spring-util-3.1.xsd"> 

    <http pattern="/resources" security="none" /> 

    <http auto-config="false" use-expressions="true" entry-point- ref="authenticationEntryPoint"> 
     <custom-filter position="BASIC_AUTH_FILTER" ref="loginFilter"/> 
     <intercept-url pattern="/login" access="permitAll" /> 
     <intercept-url pattern="/favicon.ico" access="permitAll"/> 
    </http> 

    <beans:bean id="authenticationEntryPoint" class="com.my.org.MyAuthenticationEntryPoint"/> 


    <beans:bean id="loginFilter" 
     class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
     <beans:property name="authenticationManager" ref="authenticationManager"/> 
     <beans:property name="filterProcessesUrl" value="/j_spring_security_check"/> 
     <beans:property name="authenticationSuccessHandler" > 
      <beans:bean class="com.my.org.MyAuthenticationSuccessHandler"/> 
    </beans:property> 
     <beans:property name="authenticationFailureHandler"> 
      <beans:bean class="com.my.org.MyAuthenticationFailureHandler"/> 
     </beans:property> 
    </beans:bean> 

    <authentication-manager alias="authenticationManager"> 
      <authentication-provider user-service-ref="customUserDetailsService"> 
        <password-encoder hash="sha"/> 
      </authentication-provider> 
    </authentication-manager> 

</beans:beans> 

CustomUserDetailsS​​ervice

/** 
* A custom {@link UserDetailsService} where user information 
* is retrieved from a JPA repository 
*/ 
@Service 
@Transactional(readOnly = true) 
public class CustomUserDetailsService implements UserDetailsService { 

private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class); 

@Autowired 
private UserRepository userRepository; 

/** 
* Returns a populated {@link UserDetails} object. 
* The username is first retrieved from the database and then mapped to 
* a {@link UserDetails} object. 
*/ 
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
    try { 

     logger.info("username-1-->"+username); 
     com.cbr.model.User domainUser = userRepository.findByUsername(username); 
     logger.info("domainUser-1-->"+domainUser.getPassword()); 
     logger.info("role-1-->"+domainUser.getRole().getRole()); 

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

     return new User(
       domainUser.getUsername(), 
       domainUser.getPassword().toLowerCase(), 
       enabled, 
       accountNonExpired, 
       credentialsNonExpired, 
       accountNonLocked, 
       getAuthorities(domainUser.getRole().getRole())); 

    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

/** 
* Retrieves a collection of {@link GrantedAuthority} based on a numerical role 
* @param role the numerical role 
* @return a collection of {@link GrantedAuthority 
*/ 
public Collection<? extends GrantedAuthority> getAuthorities(Integer role) { 
    List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role)); 
    return authList; 
} 

/** 
* Converts a numerical role to an equivalent list of roles 
* @param role the numerical role 
* @return list of roles as as a list of {@link String} 
*/ 
public List<String> getRoles(Integer role) { 
    List<String> roles = new ArrayList<String>(); 

    if (role.intValue() == 1) { 
     roles.add("ROLE_USER"); 
     roles.add("ROLE_ADMIN"); 

    } else if (role.intValue() == 2) { 
     roles.add("ROLE_USER"); 
    } 

    return roles; 
} 

/** 
* Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects 
* @param roles {@link String} of roles 
* @return list of granted authorities 
*/ 
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) { 
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    for (String role : roles) { 
     authorities.add(new SimpleGrantedAuthority(role)); 
    } 
    return authorities; 
} 

}

MyAuthenticationEntryPoint

public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { 

    private Log log = LogFactory.getLog(MyAuthenticationEntryPoint.class); 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 

     log.info("point-1"); 

     response.sendError(HttpServletResponse.SC_FORBIDDEN); 
    } 
} 

MyAuthenticationSuccessHandler

public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { 

    private Log log = LogFactory.getLog(MyAuthenticationSuccessHandler.class); 

    @Override 
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException { 
     // This is actually not an error, but an OK message. It is sent to avoid redirects. 
     log.info("point-2"); 
     response.sendError(HttpServletResponse.SC_OK); 
    } 
} 

MyAuthenticationFailureHandler

public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { 

    private Log log = LogFactory.getLog(MyAuthenticationFailureHandler.class); 

    @Override 
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException exception) throws IOException, ServletException { 
     log.info("point-3"); 
     response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage()); 
    } 
} 

當我嘗試登錄,它涉及到CustomUserDetailsS​​ervice併成功檢索數據庫用戶的詳細信息。

但它總是訪問authenticationFailureHandler憑證是否正確。 (INFO : com.my.org.MyAuthenticationFailureHandler - point-3

任何人都可以請幫助我嗎?感謝

回答

3

您配置的驗證提供商使用sha密碼編碼(<password-encoder hash="sha"/>),這意味着其將SHA-編碼在傳入登錄請求呈現的密碼,並與存儲在UserDetails對象的密碼比較該編碼值(因此預計也會被編碼)。在CustomUserDetailsService.loadUserByUsername()中創建UserDetails對象時,將從存儲庫加載用戶,並將其密碼與toLowerCase()一起轉換。現在,你爲什麼要這樣做?該值應該是一個sha編碼的密碼。通過轉換密碼的散列,您可以保證用戶將無法使用其原始密碼登錄。 但即使您以純文本存儲密碼(在這種情況下應該刪除password-encoder配置),爲什麼要在UserDetails中將其設爲小寫?如果你這樣做,並且用戶將他的密碼設置爲「祕密」,他以後只能以「祕密」進行認證。

+0

非常感謝。 我沒有注意到你的積分,因爲衝。 我的問題已修復。 – Unknown 2013-03-12 07:08:27

相關問題