Spring Security:控制器中的身份验证详细信息为null

时间:2018-04-13 10:00:43

标签: java spring spring-security spring-session

尝试将Spring Session(到Redis)与Spring Security(基于DB)结合起来。身份验证工作正常,如果我添加监听器:

import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpSession;

@Component
public class AuthenticationSuccessListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {


    @Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("authentication: " + authentication.getName());

        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession currentSession = attr.getRequest().getSession();
        System.out.println("session: " + currentSession.getAttribute("SESSION_DETAILS"));
    }
}

然后很好地打印:

authentication: admin
session: app.session.SessionDetails@694daf33

Redis商店也会更新:

127.0.0.1:6379> keys *
1) "spring:session:sessions:c7b0fc2c-3148-4895-9aef-78dfc8443585"
2) "spring:session:expirations:1523615100000"
3) "spring:session:sessions:expires:02acfbd4-93e7-44dc-9b61-38473a8a9ae7"
4) "spring:session:sessions:expires:c7b0fc2c-3148-4895-9aef-78dfc8443585"
5) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:admin"

但是当我进入@Controller时:

@RequestMapping("/")
public String index(Principal principal, Model model) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    System.out.println("authentication: " + authentication.getName());

    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    HttpSession currentSession = attr.getRequest().getSession();
    System.out.println("session: " + currentSession.getAttribute("SESSION_DETAILS"));

    return "index";
}

然后我看到以下内容:

authentication: null
session: app.session.SessionDetails@1225ad92

创建了新会话,即可,但身份验证详细信息已消失。这是一个很大的惊喜,因为安全配置只允许授权请求:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();
}

总结一下,我看到了安全内容,但授权详细信息设置为null。怎么样?

1 个答案:

答案 0 :(得分:0)

找到了解决方案。即使您的CustomUserDetails类实现Serializable并以某种方式创建:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional<User> optionalUsers = userRepository.findByUsername(username);

    optionalUsers
            .orElseThrow(() -> new UsernameNotFoundException("Username not found"));
    return optionalUsers
            .map(CustomUserDetails::new).get();
}

然后Spring Secruity要求User也实施Serializable。不要问我为什么。魔法。