spring-security 使用Spring-Session时更新Session中的主体

iecba09b  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(199)

我们已经用我们自己的User对象扩展了主体。这样,每个请求都可以使用该对象。当用户更新他的信息时,主体需要用这个新数据更新。当不使用spring-session时,this method works。但是,使用spring-session时,它不需要。
我检查了spring-session代码,RedisOperationsSessionRepository:save(RedisSession session)只调用session.saveDelta()session.saveDelta()只保存更改过的属性。
注意--更新主体的位置在服务层,因此我们无法访问SessionAuthenticationStrategy

smdnsysy

smdnsysy1#

找到了一种方法来做到这一点,所以回答我自己的问题。Spring-security将上下文存储为HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY中的一个属性。因此,手动更新密钥(而不是通过Spring-Session)会导致更新Principal。

httpSession.setAttribute(
  HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
  SecurityContextHolder.getContext()
);
z4bn682m

z4bn682m2#

设置一个新的Authentication对象就足够了。您可以重新创建它,重新使用旧对象的某些部分:

final Authentication oldAuth = SecurityContextHolder.getContext().getAuthentication();
final Authentication newAuth = new PreAuthenticatedAuthenticationToken(
        newDetails, oldAuth.getCredentials(), oldAuth.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);

如果对Authentication的引用发生了变化,这将触发对会话存储的更新(无论是Redis还是其他什么)...
设置特殊的会话属性HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY(常量"SPRING_SECURITY_CONTEXT"分布在Spring Security类中)也可能会触发一个新值通过会话存储(如Redis或DB)的传播,例如在RedisSessionRepository中,attributeName被放置到delta中保存:

@Override
public void setAttribute(String attributeName, Object attributeValue) {
    this.cached.setAttribute(attributeName, attributeValue);
    this.delta.put(getAttributeKey(attributeName), attributeValue);
    flushIfRequired();
}

相关问题