본문 바로가기
spring/spring security

[Spring Security] redis 세션에서 SecurityContext 수정

by moonsiri 2021. 7. 12.
728x90
반응형

FindByIndexNameSessionRepository의 save 메소드를 사용하여 SecurityContext 수정할 수 있습니다.

 

@Resource(name = "sessionRepository")
private FindByIndexNameSessionRepository<Session> findByIndexNameSessionRepository;

public void refreshSecurityContext(String targetUsername) {
    // targetUsername의 session 모두 조회
    Map<String, Session> sessionMap = findByIndexNameSessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, targetUsername);

    for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
        Session session = entry.getValue();

        // get contextHolder
        // SecurityContext securityContext = SecurityContextHolder.getContext();
        SecurityContext securityContext = session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
        if (securityContext == null) {
            continue;
        }

        // get UserDetails
        UserDetails userDetails = (UserDetails) securityContext.getAuthentication().getPrincipal();

        // userDetails 수정 영역

        // set securityContext
        Authentication newAuth = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
        securityContext.setAuthentication(newAuth);

        session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
        findByIndexNameSessionRepository.save(session);
    }
}
더보기
@Resource(name = "sessionRepository")
private FindByIndexNameSessionRepository<Session> findByIndexNameSessionRepository;

@Resource
private RedisCommands<byte[], byte[]> redisCommands;

private static final String redisNamespace = "siri";
private static final String SESSION_KEY_PATTERN = redisNamespace + ":sessions:%s";
private static final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
private static final JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
private static final byte[] HASH_KEY_OF_SPRING_SECURITY_CONTEXT = stringRedisSerializer.serialize("sessionAttr:" + SPRING_SECURITY_CONTEXT_KEY);

private void refreshSecurityContext(String targetUsername) {

    Map<String, Session> sessionMap = findByIndexNameSessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, targetUsername);

    for (String key : sessionMap.keySet()) {
        byte[] sessionKey = String.format(SESSION_KEY_PATTERN, key).getBytes();
        if (redisCommands.exists(sessionKey) == 0) {
            continue;
        }
        
        // get contextHolder
        byte[] sessionAddInfoAsBytes = redisCommands.hget(sessionKey, HASH_KEY_OF_SPRING_SECURITY_CONTEXT);
        SecurityContext securityContext = (SecurityContext)jdkSerializationRedisSerializer.deserialize(sessionAddInfoAsBytes);
        if (securityContext == null) {
            continue;
        }

        // get UserDetails
        UserDetails userDetails = (UserDetails) securityContext.getAuthentication().getPrincipal();

        // userDetails 수정

        // set securityContext
        Authentication newAuth = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
        securityContext.setAuthentication(newAuth);
        redisCommands.hset(sessionKey, HASH_KEY_OF_SPRING_SECURITY_CONTEXT, jdkSerializationRedisSerializer.serialize(securityContext));
    }
}

 

findByIndexNameSessionRepository.getById(sessionKey); 를 사용하면 Session을 조회 할 수 있고,

findByIndexNameSessionRepository.deleteById(sessionKey); 를 사용하면 session을 제거할 수도 있습니다.

728x90
반응형

댓글