2013-03-13 114 views
2

我第一次实现了Spring Security并且使用了持久性令牌方法。然后我实现了Spring Social,经过漫长的斗争,终于能够实现它。我的UserConnection表中正在创建相应的行。春季社交与春季安全 - UserDetailsS​​ervice在SignInAdapter后被调用

我的问题是,当用户登录到我的应用程序与Facebook,我的SignInAdapterImp被调用,因为它应该。我在这里做用户认证。但是,之后,我的UserDetailsS​​erviceImp立即被调用,这本质上是试图再次验证用户。这是我设置的用于验证非社会用户的类。

我猜测它与我的Spring Security设置有关,所以我发布了我的security.xml文件。任何和所有的帮助表示赞赏。

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

<!-- To allow standards-based @Secured annotation --> 
<!-- global-method-security secured-annotations="enabled" /--> 

<!-- http pattern="/signup" security="none"/> 
<http pattern="/singin" security="none"/ --> 

<http create-session="stateless" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true"> 
    <intercept-url pattern="/connect/**" access="ROLE_USER" /> 
    <!--NOT NEEDED WITH ANNOTATIONS: intercept-url pattern="/services/schedule/**" access="ROLE_USER, ROLE_ADMIN"/ -->  
    <custom-filter ref="userPassAuthenticationFilter" before="FORM_LOGIN_FILTER"/> 
    <custom-filter ref="rememberMeFilter" position="FIRST" /> 
    <!-- Adds a logout filter to Spring Security filter chain --> 
    <logout logout-url="/services/auth/logout" delete-cookies="true" invalidate-session="true" success-handler-ref="restLogoutSuccessHandler"/> 
    <remember-me key="rememberMeKey" user-service-ref="customUserDetailsService"/> 
</http> 

<!-- initialized the AuthenticationEntryPoint bean --> 
<beans:bean id="restAuthenticationEntryPoint" class="com.touchvision.pilot.security.RestAuthenticationEntryPoint" /> 

<!-- the customAuthenticationFilter custom filter definition --> 
<beans:bean id="userPassAuthenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
    <beans:property name="authenticationManager" ref="authenticationManager"/> 
    <beans:property name="rememberMeServices" ref="rememberMeServices"/> 
    <beans:property name="authenticationSuccessHandler" ref="mySuccessHandler"/> 
    <beans:property name="filterProcessesUrl" value="/services/auth/login"/> 
    <beans:property name="usernameParameter" value="username"/> 
    <beans:property name="passwordParameter" value="password"/> 
    <beans:property name="postOnly" value="false"/> 
</beans:bean> 


<!-- the Remember Me bean definition --> 
<beans:bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices"> 
    <beans:property name="key" value="springRocks"/> 
    <beans:property name="alwaysRemember" value="true" /> 
    <!-- NOT NEEDED WITH ALWAYSREMEMBER: beans:property name="parameter" value="persistLogin"/ --> <!-- This is used to change the param from _spring_security_remember_me --> 
    <beans:property name="userDetailsService" ref="customUserDetailsService"/> 
    <beans:property name="tokenRepository" ref="tokenRepository"/> 
</beans:bean> 

<!-- the remember-me filter bean --> 
<beans:bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter"> 
    <beans:property name="rememberMeServices" ref="rememberMeServices"/> 
    <beans:property name="authenticationManager" ref="authenticationManager" /> 
</beans:bean> 

<!-- the remember-me authentication provider bean definition --> 
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider"> 
    <beans:property name="key" value="springRocks"/> 
</beans:bean> 

<!-- Instantiates the bean for the token provider --> 
<beans:bean id="tokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl"> 
    <beans:property name="createTableOnStartup" value="false"/> 
    <beans:property name="dataSource" ref="dataSource"/> 
</beans:bean> 

<!-- Configures a custom authentication success handler that returns HTTP status code 200 --> 
<beans:bean id="mySuccessHandler" class="com.touchvision.pilot.security.RestAuthenticationSuccessHandler"/> 

<!-- Configures a custom authentication failure handler that returns HTTP status code 401 --> 
<beans:bean id="restAuthenticationFailureHandler" class="com.touchvision.pilot.security.RestAuthenticationFailureHandler"/> 

<!-- Configures a custom logout success handler that returns HTTP status code 200 --> 
<beans:bean id="restLogoutSuccessHandler" class="com.touchvision.pilot.security.RestLogoutSuccessHandler"/> 

<!-- Declare an authentication-manager to use a custom userDetailsService --> 
<authentication-manager alias="authenticationManager"> 
     <authentication-provider user-service-ref="customUserDetailsService"> 
       <password-encoder ref="passwordEncoder"/> 
     </authentication-provider>   
     <authentication-provider ref="rememberMeAuthenticationProvider" /> 
</authentication-manager> 

<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database --> 
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> 

<!-- A custom service where Spring will retrieve users and their corresponding access levels --> 
<beans:bean id="customUserDetailsService" class="com.touchvision.pilot.security.CustomUserDetailsService"/> 

</beans:beans> 

编辑:这里是我的SignInAdapter签到()实现:

@Override 
public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) { 
    logger.info("*************** in SignInAdapterImp signIn() w/ localUserId = " + localUserId +" ****************"); 

    User user = userRepo.findById(Integer.parseInt(localUserId)); 

    // Create a list of grants for this user 
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    logger.info("Grant ROLE_USER to this user"); 
    authorities.add(new GrantedAuthorityImpl("ROLE_USER")); 

    Authentication authentication = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), authorities); 
    SecurityContextHolder.getContext().setAuthentication(authentication); 

    // set remember-me cookie 
    persistentTokenRememberMeServices.loginSuccess(
     (HttpServletRequest) request.getNativeRequest(), 
     (HttpServletResponse) request.getNativeResponse(), 
     authentication); 

    return null; 
} 
+0

你能显示SignInAdapter.signIn(...)实现的代码吗?你有没有尝试打开org.springframework.security包的调试日志记录(可能在这些调用之间有一些有趣的事情)? – 2013-03-14 09:47:12

+0

感谢您的帮助!我添加了我正在使用的signIn()实现。另外,我正在使用log4j,并且已经打开了调试日志记录。我如何特别打开org.springframework.security包的日志记录? – SBerg413 2013-03-14 14:42:02

+0

就像'log4j.logger.org.springframework.security = DEBUG'(如果使用属性conf文件)。 – 2013-03-14 14:55:55

回答

0

原来,我曾在HTTP过滤器列表中重复的过滤器。我为记忆功能定义了2个过滤器。这里是最终实现的过滤器集:

<http entry-point-ref="restAuthenticationEntryPoint" use-expressions="true"> 
     <!--NOT NEEDED WITH ANNOTATIONS: intercept-url pattern="/services/schedule/**" access="ROLE_USER, ROLE_ADMIN"/ -->  
     <custom-filter before="FORM_LOGIN_FILTER" ref="userPassAuthenticationFilter" /> 
     <custom-filter position="REMEMBER_ME_FILTER" ref="rememberMeFilter" /> 
     <custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />  
    </http>