授权检查与Spring和Jobrunr

huangapple go评论67阅读模式
英文:

Authorization checks with Spring & Jobrunr

问题

我正在创建一个具有4个角色的应用程序。我在数据库中没有存储权限,只有角色。

在控制器层面,我仅限制我的路由给特定的角色,例如:

@PreAuthorize("hasRole('ADMIN')")

在我的服务方法中,我进行了更详细的检查,根据需要进行操作。

然而,我在服务中设置授权条件的问题是,它仅在SecurityContextHolder.getContext()不为空时才有效。

我意识到,例如在我的Jobrunr工作之一中,这可能是问题。

因此,我将我的服务注入到我的作业中,我想调用一个方法,但它崩溃了,因为它无法检索经过身份验证的用户。

是否有一种方法可以在作业中手动验证用户,这是一个好方法吗?


根据@Ken Chan的回复 - 代码不起作用:

Jobrunr作业:

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class InactiveUsersEmail implements JobRequest {
    private Integer userId;

    @Override
    public Class<InactiveUsersEmailHandler> getJobRequestHandler() {
        return InactiveUsersEmailHandler.class;
    }
}

使用DelegatingSecurityContextRunnable运行它:

Stream<DelegatingSecurityContextRunnable> jobs = this.userService
    .findAll()
    .map(user -> {
        Runnable task = () -> new InactiveUsersEmail(user.getId());
        return new DelegatingSecurityContextRunnable(task, this.authorizationComponent.getSecurityContext());
    });

// 这里不起作用:
// 无法解析方法'enqueue(java.util.stream.Stream<org.springframework.security.concurrent.DelegatingSecurityContextRunnable>)'
BackgroundJobRequest.enqueue(jobs);

如您所述,您遇到了BackgroundJobRequest.enqueue方法无法解析的问题。这可能是由于库或框架版本之间的不兼容性或配置问题导致的。您可能需要查看文档或相关文档,以确定正确的方法来排队Jobrunr作业。

英文:

I'm creating an app with 4 roles. I don't have permissions stored in my database, just the roles.

At the controller level, I restrict my routes only to certain roles, for example :

@PreAuthorize(&quot;hasRole(&#39;ADMIN&#39;)&quot;)

And in my service's methods, I did a more thorough check as needed.

However, the problem I have with having authorization conditions in my services is that it only works if the SecurityContextHolder.getContext() is not null.

And I realized that this could be the case, for example, in one of my jobs with Jobrunr.

So I inject my service into my job and I want to call a method, but it crashes because it can't retrieve the authenticated user.

Is there a way to manually authenticate a user in the job, is this a good way to do it?


Update following @Ken Chan's reply - code not working :

Jobrunr job :

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class InactiveUsersEmail implements JobRequest {
    private Integer userId;

    @Override
    public Class&lt;InactiveUsersEmailHandler&gt; getJobRequestHandler() {
        return InactiveUsersEmailHandler.class;
    }
}

Run it using DelegatingSecurityContextRunnable:

Stream&lt;DelegatingSecurityContextRunnable&gt; jobs = this.userService
    .findAll()
    .map(user -&gt; {
        Runnable task = () -&gt; new InactiveUsersEmail(user.getId());
        return new DelegatingSecurityContextRunnable(task, this.authorizationComponent.getSecurityContext());
    });

// here not working: 
// cannot resolve method &#39;enqueue(java.util.stream.Stream&lt;org.springframework.security.concurrent.DelegatingSecurityContextRunnable&gt;)&#39;
BackgroundJobRequest.enqueue(jobs);

答案1

得分: 1

您可以通过DelegatingSecurityContextRunnable来包装提交给Jobrunr的Runnable

它需要您为运行Runnable定义SecurityContext,并会在运行任务之前和之后设置和清理SecurityContext

在配置SecurityContext时,最好与现有的身份验证机制保持一致,以定义一个具有足够权限运行作业的Authentication对象。

以下是一个入门示例:


//提交给Jobrunr的原始可运行任务
Runnable task = () -&gt; System.out.println("执行一些任务");

//配置具有足够权限执行任务的SecurityContext

SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
// 这里不管用户名和密码的值是什么。只需确保该用户具有Admin权限并且帐户已启用
User user = new User("admin", "password", true, true, true, true, grantedAuthorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
securityContext.setAuthentication(authentication);

//通过DelegatingSecurityContextRunnable包装任务
DelegatingSecurityContextRunnable securedRunnable = new DelegatingSecurityContextRunnable(task, securityContext);

//将受保护的任务提交给Jobrunr
BackgroundJob.enqueue(()-&gt;securedRunnable.run());

英文:

You can wrap the Runnable that is submitted to Jobrunr by DelegatingSecurityContextRunnable

It requires you to define the SecurityContext for running the Runnable and it will take care of setting up and cleaning SecurityContext before and after running the task.

When configuring the SecurityContext , it is better to align with the existing used authentication mechanism to define an Authentication object that has enough permission to run the job.

Below is a getting started example :


//origin runnable task submitted to Jobrunr
Runnable task = () -&gt; System.out.println(&quot;doing some task&quot;);

//Configure the SecurityContext that has enough permission to execute the task

SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
List&lt;GrantedAuthority&gt; grantedAuthorities = new ArrayList&lt;&gt;();
grantedAuthorities.add(new SimpleGrantedAuthority(&quot;ROLE_ADMIN&quot;));
// Here it does not matter what values username and password are. Just ensure this user has the the Admin GrantedAuthority and his account is enabled
User user = new User(&quot;admin&quot;, &quot;password&quot;, true, true, true, true, grantedAuthorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
securityContext.setAuthentication(authentication);

//wrap the task by DelegatingSecurityContextRunnable
DelegatingSecurityContextRunnable securedRunnable = new DelegatingSecurityContextRunnable(task,securityContext);

//Submit the secured task to Jobrunr
BackgroundJob.enqueue(()-&gt;securedRunnable.run());

huangapple
  • 本文由 发表于 2023年5月28日 03:57:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76348789.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定