Spring Security:在后台任务中使用@PreAuthorize调用方法的正确方法是什么?

Pop*_*los 6 spring spring-security

我有一个用@PreAuthorize保护的方法

@PreAuthorize("hasRole('ROLE_ADMIN') and (#action.userId != principal.id)")
public void execute(EditAction action)
Run Code Online (Sandbox Code Playgroud)

现在我需要从后台任务中调用此方法.如果我只是运行此代码 - 我捕获一个异常:

AuthenticationCredentialsNotFoundException:在SecurityContext中找不到Authentication对象

好像,我需要将任何身份验证设置为SecurityContext.我可以:

  1. 为后台任务编写一些自定义AuthenticationToken.
  2. 对假用户使用UsernamePasswordAuthenticationToken.
  3. 不要在后台任务中使用安全方法.
  4. 还要别的吗?

什么是正确的方法?

Mad*_*omy 2

在这种情况下,可以选择手动解决方法:

(1) 如果这是一份独立的工作,

创建一个 Authentication 对象,并在调用安全方法之前将其设置为安全上下文。安全方法执行完毕后,从安全上下文中删除 Authentication 对象。

public final class AuthenticationUtil {

//Ensures that this class cannot be instantiated
private AuthenticationUtil() {
}

public static void clearAuthentication() {
    SecurityContextHolder.getContext().setAuthentication(null);
}

public static void configureAuthentication(String role) {
    Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(role);
    Authentication authentication = new UsernamePasswordAuthenticationToken(
            "user",
            role,
            authorities
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);
}
Run Code Online (Sandbox Code Playgroud)

所以它看起来像

AuthenticationUtil.configureAuthentication(role);
// Call to the secured method 
AuthenticationUtil.clearAuthentication();
Run Code Online (Sandbox Code Playgroud)

(2) 对于Web应用程序,我们不能将身份验证对象设置为空,所以不要调用

AuthenticationUtil.configureAuthentication(role);
// call to the secured method 
Run Code Online (Sandbox Code Playgroud)