尝试将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。怎么样?
答案 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
。不要问我为什么。魔法。