Spring security Remember-me doesn't work

 ̄綄美尐妖づ 提交于 2019-12-25 14:14:58

问题


I'm trying to apply spring security with custom user detail service and custom authentication provider. Also, I'm trying to apply the remember-me functionality.

However, somehow, after I configured the custom user detail service and custom authentication provider, the remember me stop working.

When I check cookies from the client browser, it has the remember-me cookie. But, if I redeploy (restart) the server or restart the client browser, it redirects to the login page.

Here I'm attaching my configuration and custom files.

<?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:security="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

       <!-- enable use-expressions -->
       <security:annotation-config/>
       <http auto-config="false" use-expressions="true">

              <headers>
                     <cache-control />
              </headers>


              <intercept-url pattern="/resources/**" access="permitAll()"/>
              <intercept-url pattern="/signin" access="permitAll()" />
              <intercept-url pattern="/403" access="permitAll()" />
              <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

              <!-- redirect to 403 access denied <intercept-url pattern="/update**" access="hasRole('ROLE_ADMIN')
                  and isFullyAuthenticated()" /> -->

              <form-login login-page="/signin"
                          default-target-url="/"
                          authentication-failure-url="/signin?error"
                          username-parameter="username"
                          password-parameter="password"
                          login-processing-url="/auth/login_check"
                          authentication-success-handler-ref="loginSuccessHandler" />

              <logout logout-url="/logout" logout-success-url="/signin?logout" delete-cookies="JSESSIONID" />
              <!-- enable csrf protection -->
              <!--<csrf disabled="true"/>-->

              <!--<remember-me-->
                      <!--token-validity-seconds="1209600"-->
                      <!--remember-me-parameter="remember-me"-->
                      <!--data-source-ref="dataSource" user-service-ref="customUserDetailService"/>-->
               <remember-me services-ref="rememberMeServices" />
                <csrf disabled="true"/>
            <!--<custom-filter ref="statelessCSRFFilter" before="CSRF_FILTER"/>-->


       </http>

       <!-- Select users and user_roles from database -->
       <!--<authentication-manager>-->
              <!--<authentication-provider>-->
                     <!--<jdbc-user-service data-source-ref="dataSource"-->
                                        <!--users-by-username-query="select username,password, enabled from users where username=?"-->
                                        <!--authorities-by-username-query="select username, role from user_roles where username =?  "-->
                             <!--group-authorities-by-username-query="select  g.id, g.group_name, ga.authority from groups g, group_members gm, group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id"/>-->
              <!--</authentication-provider>-->
       <!--</authentication-manager>-->


        <beans:bean id="customUserDetailService" class="com.euroscope.app.service.security.CustomUserService"></beans:bean>

        <beans:bean id="customAuthenticationProvider" class="com.euroscope.app.handler.CustomAuthenticationProvider"></beans:bean>

        <beans:bean id="loginSuccessHandler" class="com.euroscope.app.handler.LoginSuccessHandler"></beans:bean>





    <!--<beans:bean id="statelessCSRFFilter" class="com.euroscope.app.filter.StatelessCSRFFilter" />-->

        <beans:bean id="rememberMeFilter" class= "org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
            <beans:constructor-arg ref="authenticationManager"/>
            <beans:constructor-arg ref="rememberMeServices"/>
        </beans:bean>

        <beans:bean id="rememberMeServices" class= "org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
            <beans:constructor-arg value="euroscope"/>
            <beans:constructor-arg ref="customUserDetailService"/>
            <beans:constructor-arg ref="tokenRepository" />
            <beans:property name="alwaysRemember" value="true" />
        </beans:bean>

        <beans:bean id="rememberMeAuthenticationProvider" class= "org.springframework.security.authentication.RememberMeAuthenticationProvider">
            <beans:constructor-arg value="euroscope"/>
        </beans:bean>

        <beans:bean id="tokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
            <beans:property name="dataSource" ref="dataSource"/>
        </beans:bean>


        <authentication-manager alias="authenticationManager">

            <authentication-provider ref="rememberMeAuthenticationProvider" />
            <authentication-provider ref="customAuthenticationProvider" />
            <authentication-provider user-service-ref="customUserDetailService" />
        </authentication-manager>

</beans:beans>

Login Success handler

@Component
@Slf4j
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException
    {

        HttpSession session = request.getSession();
        Employee employee = (Employee)auth.getPrincipal();
        log.debug("Employee : "+employee);
        session.setAttribute("employee",employee);
        response.sendRedirect(request.getContextPath() + "/");
    }
}

package com.euroscope.app.handler;

import com.euroscope.app.domain.security.Employee;
import com.euroscope.app.service.security.CustomUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * Created by ksyeng on 7/9/15.
 */
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

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

    @Autowired
    CustomUserService customUserService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {


        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        Employee employee;
        Collection<? extends GrantedAuthority> authorities;

        try {
            logger.debug("Custom Authentication : "+authentication);
            employee = (Employee)customUserService.loadUserByUsername(username);
//            employee = customUserService.loadUserByUsername(username);

//            String hashedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));

//            log.info("username : " + username + " / password : " + password + " / hash password : " + hashedPassword);
            logger.debug("Username : " + employee.getUsername() + " / Password : " + employee.getPassword());

//            if (!hashedPassword.equals(user.getPassword())) throw new BadCredentialsException("비밀번호가 일치하지 않습니다.");

            authorities = employee.getAuthorities();
            return new UsernamePasswordAuthenticationToken(employee, password, authorities);
        } catch(UsernameNotFoundException e) {
            e.printStackTrace();
            logger.debug(e.toString());
            throw new UsernameNotFoundException(e.getMessage());
        } catch(BadCredentialsException e) {
            e.printStackTrace();
            logger.debug(e.toString());
            throw new BadCredentialsException(e.getMessage());
        } catch(Exception e) {
            e.printStackTrace();
            logger.debug(e.toString());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

Custom User Service

package com.euroscope.app.service.security;

import com.euroscope.app.domain.security.Employee;
import com.euroscope.app.domain.security.Role;
import com.euroscope.app.mapper.security.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * Created by ksyeng on 7/9/15.
 */
@Slf4j
@Service
public class CustomUserService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        Employee employee = userMapper.getUser(username);
        ArrayList<Role> authList = userMapper.getRoles(username);
        log.debug("Auth Roles : "+authList.toString());
        employee.setAuthorities(authList);

        if(employee == null){
            throw new UsernameNotFoundException("Can't Find Any Matching User");
        }

        log.debug(employee.toString());

        return employee;
    }
}

回答1:


Whatever authentication filters (ie, subclasses of AbstractAuthenticationProcessingFilter) you are using will need to be aware of the RememberMeServices, for example:

<beans:bean .. class="x.x..YourCustomAuthenticationFilter">
  <beans:property name="rememberMeServices" ref="rememberMeServices"/>
  <beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>

and RememberMeAuthenticationFilter should be registered after YourCustomAuthenticationFilter



来源:https://stackoverflow.com/questions/31382144/spring-security-remember-me-doesnt-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!