首页 > 解决方案 > 如何从 Spring Boot 中的 Scheduled 更新用户信息

问题描述

当我尝试将用户保存在计划任务中,然后通过 Authentication.getPrincipal() 在控制器中访问它时,尽管底层数据库记录发生更改,但它不会得到更新。

@Scheduled(fixedRate = 10_000)
public void job() {
    User user = userRepo.findById(1).get();
    user.setEmail("someNewEmail@gmail.com");
    userRepo.save(user);
}

我使用 Spring Security,并且我相信用户的信息会以某种方式缓存在 SecurityContextHolder 中,因此不允许我使用已保存用户的更新值。

此外,如果我执行 SignOut - SignIn 数据会更新,但这不能被视为解决方案。

作为一种解决方法,我尝试使用自动装配的 EntityManager 并在获取数据之前用用户刷新记录,但这假设我应该为需要获取用户的每个请求执行此操作。也不是最好的解决方案

除用户外的其他实体保存良好

标签: spring-bootspring-security

解决方案


我最终获得了一个带有容器的服务,该容器包含我需要更改其数据的用户。

@Service
@Getter
@Setter
public class AuthService {

    private List<User> users = new CopyOnWriteArrayList<>();

}

而且我还按照 Mehdi 的建议实施了一个过滤器。

public class AuthFilter extends GenericFilterBean {

    @Autowired
    private AuthService authService;
    @Autowired
    private UserRepository userRepo;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth == null || !auth.isAuthenticated() || !(auth.getPrincipal() instanceof UserDetails)) {
            chain.doFilter(request, response);
            return;
        }
        User currUser = ... // getting current user from auth
        if (authService.getUsers().contains(currUser)) {
            UserDetails details = myUserDetailsService.loadUserByUsername(currUser.getFirstName());
            Authentication updatedAuth = new UsernamePasswordAuthenticationToken(details, currUser.getPassword(), details.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(updatedAuth);
            authService.getUsers().remove(currUser);
        }
        chain.doFilter(request, response);
    }
}

很遗憾,spring 没有提供一个包含所有 Authentication 对象的容器来使更改用户更容易。或者也许我没找到


推荐阅读