从安全上下文中获取当前经过身份验证的用户作为 Spring Cache 的密钥

Png*_*Png 3 java caching ehcache spring-security spring-boot

我有不带参数的方法,我想缓存返回值。作为缓存密钥,我想使用安全上下文中当前经过身份验证的用户

@Cacheable(value = "resultCache", key="#userPrincipal.id")
    public result getResult() {}
Run Code Online (Sandbox Code Playgroud)

有可能吗,还是我的想法错了。

Mar*_*gio 6

您有四种选择来实现这一目标:

  1. Authentication将对象作为方法参数发送:

    @Cacheable(value = "resultCache", key="#authentication.name")
    public Result getResult(Authentication authentication) {}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建自定义KeyGenerator并在@Cacheable注释中使用它

    public class CustomKeyGenerator implements KeyGenerator {
        @Override
        public Object generate(Object target, Method method, Object... params) {
            return SecurityContextHolder.getContext().getAuthentication().getName();
        }
    }
    
    @Configuration
    @EnableCaching
    public class CacheConfiguration {
    
        @Bean("customKeyGenerator")
        public KeyGenerator customKeyGenerator() {
            return new CustomKeyGenerator();
        }
    }
    
    @Cacheable(value = "resultCache", keyGenerator="customKeyGenerator")
    public Result getResult() {}
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建一个为您提供密钥的 bean,并通过属性中的SPeLkey引用它。我建议您采用这种方法,因为它可以让您以后更轻松地更改该值。

    @Component
    public class CacheKeyProvider {
    
        public String getUsernameKey() {
            return SecurityContextHolder.getContext().getAuthentication().getName();
        }
    }
    
    @Cacheable(value = "resultCache", key="@cacheKeyProvider.getUsernameKey()")
    public Result getResult() {}
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用类型 SpEL 表达式

    @Cacheable(value = "resultCache", key="T(org.springframework.security.core.context.SecurityContextHolder.getContext()?.authentication?.name)")
    public Result getResult() {}
    
    Run Code Online (Sandbox Code Playgroud)

请注意,我使用了示例中name的属性。Principal但是,如果您有自定义Principal对象,则可以对其进行强制转换并返回您想要的任何属性。