触发@Scheduled 时在SecurityContext 中找不到身份验证对象?
An Authentication object was not found in the SecurityContext when @Scheduled triggered?
我创建了一个 Spring Boot
应用程序,但遇到了一些可以手动或通过 @Scheduled
注释触发的端点的问题。
我遇到的问题如下:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:
An Authentication object was not found in the SecurityContext
如果进程通过 @Scheduled
调用,有没有办法触发 SecurityContext
?
我是Spring Security
的新手,我很难理解参考指南。我发现了一些类似的问题,但仍然无法理解如何将答案应用到我的案例中。
我的例子MyController
:
@Secured("ROLE_ADMIN")
@RestController
@RequestMapping(value = "/api")
public class MyController {
@Scheduled(cron = "* * * * * *")
@GetMapping(path="/data")
public void getData() {
// Do some operations
}
}
基本上,您必须使用必要的身份验证配置您的调度程序。以下几行内容:
import com.google.common.collect.ImmutableList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import java.util.List;
import java.util.concurrent.Executor;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.springframework.security.core.context.SecurityContextHolder.getContext;
@Configuration
public class SchedulerConfiguration implements SchedulingConfigurer {
private static final String KEY = "spring";
private static final String PRINCIPAL = "spring";
private static final List<SimpleGrantedAuthority> AUTHORITIES = ImmutableList.of(new SimpleGrantedAuthority("ADMIN"));
@Override
public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public Executor taskExecutor() {
final AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(KEY, PRINCIPAL, AUTHORITIES);
final SecurityContext securityContext = getContext();
securityContext.setAuthentication(token);
return new DelegatingSecurityContextScheduledExecutorService(newSingleThreadScheduledExecutor(), securityContext);
}
}
然后你可以用@Secured("hasAuthority('ADMIN')")
注释你的控制器。
@Scheduled
方法不应该是@Secured
。计划的方法已经在受信任的代码中。
重构您的代码,例如
@Secured("ROLE_ADMIN")
@RestController
@RequestMapping(value = "/api")
public class MyController {
@Autowired
private MyService myService;
@PostMapping(path="/run")
public void runJobs() {
myService.runJobs();
}
}
@Service
public class MyService {
@Scheduled(cron = "* * * * * *")
public void runJobs() {
// Do some operations
}
}
我创建了一个 Spring Boot
应用程序,但遇到了一些可以手动或通过 @Scheduled
注释触发的端点的问题。
我遇到的问题如下:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
如果进程通过 @Scheduled
调用,有没有办法触发 SecurityContext
?
我是Spring Security
的新手,我很难理解参考指南。我发现了一些类似的问题,但仍然无法理解如何将答案应用到我的案例中。
我的例子MyController
:
@Secured("ROLE_ADMIN")
@RestController
@RequestMapping(value = "/api")
public class MyController {
@Scheduled(cron = "* * * * * *")
@GetMapping(path="/data")
public void getData() {
// Do some operations
}
}
基本上,您必须使用必要的身份验证配置您的调度程序。以下几行内容:
import com.google.common.collect.ImmutableList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import java.util.List;
import java.util.concurrent.Executor;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.springframework.security.core.context.SecurityContextHolder.getContext;
@Configuration
public class SchedulerConfiguration implements SchedulingConfigurer {
private static final String KEY = "spring";
private static final String PRINCIPAL = "spring";
private static final List<SimpleGrantedAuthority> AUTHORITIES = ImmutableList.of(new SimpleGrantedAuthority("ADMIN"));
@Override
public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public Executor taskExecutor() {
final AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(KEY, PRINCIPAL, AUTHORITIES);
final SecurityContext securityContext = getContext();
securityContext.setAuthentication(token);
return new DelegatingSecurityContextScheduledExecutorService(newSingleThreadScheduledExecutor(), securityContext);
}
}
然后你可以用@Secured("hasAuthority('ADMIN')")
注释你的控制器。
@Scheduled
方法不应该是@Secured
。计划的方法已经在受信任的代码中。
重构您的代码,例如
@Secured("ROLE_ADMIN")
@RestController
@RequestMapping(value = "/api")
public class MyController {
@Autowired
private MyService myService;
@PostMapping(path="/run")
public void runJobs() {
myService.runJobs();
}
}
@Service
public class MyService {
@Scheduled(cron = "* * * * * *")
public void runJobs() {
// Do some operations
}
}