Spring Session Redis and Spring User Session Update Security?

I am creating a spring REST web application using spring boot, spring secuirity and spring session (redis). I am building a cloud application following the gateway pattern using spring cloud and zuul proxy. As part of this template, I use a spring session to manage the HttpSesssion in redis and use this to authorize requests on my resource servers. When an operation is performed that changes the session privileges, I would like to update this object so that the user cannot log out to reflect the updates. Does anyone have a solution for this?

+4
source share
1 answer

To update credentials, you need to change the authentication object in two places. One in the context of security, and the other in the context of the request. The main object will be org.springframework.security.core.userdetails.User or extend this class (if you redefined UserDetailsService). This works to change the current user.

    Authentication newAuth = new UsernamePasswordAuthenticationToken({YourPrincipalObject},null,List<? extends GrantedAuthority>)

    SecurityContextHolder.getContext().setAuthentication(newAuth);
    RequestContextHolder.currentRequestAttributes().setAttribute("SPRING_SECURITY_CONTEXT", newAuth, RequestAttributes.SCOPE_GLOBAL_SESSION);

spring . , . , . , . "SPRING_SECURITY_CONTEXT" SecurityContextHolder. . , SpringSessionRepositoryFilter. @Order -2147483598, , , .

:

  • ( )
  • , A ,

    @Component
    @Order(UpdateAuthFilter.ORDER_AFTER_SPRING_SESSION)
    public class UpdateAuthFilter extends OncePerRequestFilter
    {
    public static final int ORDER_AFTER_SPRING_SESSION = -2147483597;
    
    private Logger log = LoggerFactory.getLogger(this.getClass());
    
    private Set<String> permissionsToUpdate = new HashSet<>();
    
    @Autowired
    private UserJPARepository userJPARepository;
    
    private void modifySessionSet(String sessionKey, boolean add)
    {
        if (add) {
            permissionsToUpdate.add(sessionKey);
        } else {
            permissionsToUpdate.remove(sessionKey);
        }
    }
    
    public void addUserSessionsToSet(UpdateUserSessionMessage updateUserSessionMessage)
    {
        log.info("UPDATE_USER_SESSION - {} - received", updateUserSessionMessage.getUuid().toString());
        updateUserSessionMessage.getSessionKeys().forEach(sessionKey -> modifySessionSet(sessionKey, true));
        //clear keys for sessions not in redis
        log.info("UPDATE_USER_SESSION - {} - success", updateUserSessionMessage.getUuid().toString());
    }
    
    @Override
    public void destroy()
    {
    
    }
    
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException
    {
        HttpSession session = httpServletRequest.getSession();
    
    if (session != null)
    {
        String sessionId = session.getId();
        if (permissionsToUpdate.contains(sessionId))
        {
            try
            {
                SecurityContextImpl securityContextImpl = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
                if (securityContextImpl != null)
                {
                    Authentication auth = securityContextImpl.getAuthentication();
                    Optional<User> user = auth != null
                                          ? userJPARepository.findByUsername(auth.getName())
                                          : Optional.empty();
    
                    if (user.isPresent())
                    {
                        user.get().getAccessControls().forEach(ac -> ac.setUsers(null));
    
                        MyCustomUser myCustomUser = new MyCustomUser (user.get().getUsername(),
                                                                     user.get().getPassword(),
                                                                     user.get().getAccessControls(),
                                                                     user.get().getOrganization().getId());
    
                        final Authentication newAuth = new UsernamePasswordAuthenticationToken(myCustomUser ,
                                                                                               null,
                                                                                               user.get().getAccessControls());
                        SecurityContextHolder.getContext().setAuthentication(newAuth);
                        session.setAttribute("SPRING_SECURITY_CONTEXT", newAuth);
                    }
                    else
                    {
                        //invalidate the session if the user could not be found
                        session.invalidate();
                    }
                }
                else
                {
                    //invalidate the session if the user could not be found
                    session.invalidate();
                }
            }
            finally
            {
                modifySessionSet(sessionId, false);
            }
        }
    }
    
    filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
    
+8

Source: https://habr.com/ru/post/1617923/


All Articles