Java 触发@Scheduled时,在SecurityContext中未找到身份验证对象?

Java 触发@Scheduled时,在SecurityContext中未找到身份验证对象?,java,spring,spring-boot,spring-security,spring-scheduled,Java,Spring,Spring Boot,Spring Security,Spring Scheduled,我创建了一个Spring-Boot应用程序,但有些端点无法手动触发或通过@Scheduled注释触发 我遇到的问题如下: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: 在SecurityContext中找不到身份验证对象 如果进程通过@Scheduled调用,是否有方法触发SecurityContext 我是Spring Security新手,很难理解参考指南。我发现

我创建了一个
Spring-Boot
应用程序,但有些端点无法手动触发或通过
@Scheduled
注释触发

我遇到的问题如下:

org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: 在SecurityContext中找不到身份验证对象

如果进程通过
@Scheduled
调用,是否有方法触发
SecurityContext

我是
Spring Security
新手,很难理解参考指南。我发现了一些类似的问题,但仍然无法理解如何将答案应用到我的案例中

my
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);
    }
}
import com.google.common.collect.ImmutableList;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.scheduling.annotation.SchedulingConfigurer;
导入org.springframework.scheduling.config.scheduledtaskregistra;
导入org.springframework.security.authentication.AnonymousAuthenticationToken;
导入org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
导入org.springframework.security.core.authority.SimpleGrantedAuthority;
导入org.springframework.security.core.context.SecurityContext;
导入java.util.List;
导入java.util.concurrent.Executor;
导入静态java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
导入静态org.springframework.security.core.context.SecurityContextHolder.getContext;
@配置
公共类SchedulerConfiguration实现SchedulingConfigurer{
私有静态最终字符串KEY=“spring”;
私有静态最终字符串PRINCIPAL=“spring”;
私有静态最终列表权限=ImmutableList.of(新的SimpleGrantedAuthority(“ADMIN”);
@凌驾
公共无效配置任务(最终计划任务登记器){
taskRegistrator.setScheduler(taskExecutor());
}
@豆子
公共执行者任务执行者(){
final AnonymousAuthenticationToken=新的AnonymousAuthenticationToken(密钥、主体、权限);
最终SecurityContext SecurityContext=getContext();
securityContext.setAuthentication(令牌);
返回新的DelegatingSecurityContextScheduledExecutorService(newSingleThreadScheduledExecutor(),securityContext);
}
}

然后,您可以使用
@Secured(“hasAuthority('ADMIN')”)
对控制器进行注释。基本上,您必须为计划程序配置必要的身份验证。以下几行中的某些内容:

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);
    }
}
import com.google.common.collect.ImmutableList;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.scheduling.annotation.SchedulingConfigurer;
导入org.springframework.scheduling.config.scheduledtaskregistra;
导入org.springframework.security.authentication.AnonymousAuthenticationToken;
导入org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
导入org.springframework.security.core.authority.SimpleGrantedAuthority;
导入org.springframework.security.core.context.SecurityContext;
导入java.util.List;
导入java.util.concurrent.Executor;
导入静态java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
导入静态org.springframework.security.core.context.SecurityContextHolder.getContext;
@配置
公共类SchedulerConfiguration实现SchedulingConfigurer{
私有静态最终字符串KEY=“spring”;
私有静态最终字符串PRINCIPAL=“spring”;
私有静态最终列表权限=ImmutableList.of(新的SimpleGrantedAuthority(“ADMIN”);
@凌驾
公共无效配置任务(最终计划任务登记器){
taskRegistrator.setScheduler(taskExecutor());
}
@豆子
公共执行者任务执行者(){
final AnonymousAuthenticationToken=新的AnonymousAuthenticationToken(密钥、主体、权限);
最终SecurityContext SecurityContext=getContext();
securityContext.setAuthentication(令牌);
返回新的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();
    }
}

@Scheduled
方法不应是
@安全的
。计划的方法已在受信任的代码中

重构你的代码,例如

@Secured("ROLE_ADMIN")
@RestController
@RequestMapping(value = "/api")
public class MyController {

    @Autowired
    private MyService myService;

    @PostMapping(path="/run")
    public void runJobs() {
        myService.runJobs();
    }
}

那代码毫无意义
@GetMapping
意味着该方法是HTTP
GET
请求的处理程序,它应该向客户端返回一些内容。您的方法不接受任何参数,也不返回任何内容,因此作为请求处理程序,它的用途是什么?触发一些后台作业。然后它应该是
POST
方法,而不是
GET
方法。@Andreas的确,您是对的!那代码毫无意义
@GetMapping
意味着该方法是HTTP
GET
请求的处理程序,它应该向客户端返回一些内容。您的方法不接受任何参数,也不返回任何内容,因此作为请求处理程序,它的用途是什么?触发一些后台作业。然后它应该是
POST
方法,而不是
GET
方法。@Andreas的确,您是对的!