Spring Security:在后台任务中调用@PreAuthorize 保护的方法的正确方法是啥?

Posted

技术标签:

【中文标题】Spring Security:在后台任务中调用@PreAuthorize 保护的方法的正确方法是啥?【英文标题】:Spring Security: What is the right way to call method secured with @PreAuthorize in background task?Spring Security:在后台任务中调用@PreAuthorize 保护的方法的正确方法是什么? 【发布时间】:2012-04-26 10:35:52 【问题描述】:

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

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

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

AuthenticationCredentialsNotFoundException:在 SecurityContext 中找不到 Authentication 对象

看来,我需要将所需的身份验证设置为 SecurityContext。我可以:

    为后台任务编写一些自定义 AuthenticationToken。 对假用户使用 UsernamePasswordAuthenticationToken。 不要在后台任务中使用安全方法。 还有其他建议吗?

什么是正确的方法?

【问题讨论】:

你能显示一些代码吗?你怎么称呼它? 这不是一个透明的调用——我们使用的是命令模式。 Secured方法是Handler的一种方法。 “后台任务”是指 jms MessageListener 或一些 @Scheduled 方法。我以某种方式调用安全方法,因为我通过处理 servlet 调用它 - 通过调度一个动作。 【参考方案1】:

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

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

在调用安全方法之前创建一个身份验证对象并将其设置为安全上下文。 在安全方法执行完毕后,从安全上下文中移除 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);

它看起来像

AuthenticationUtil.configureAuthentication(role);
// Call to the secured method 
AuthenticationUtil.clearAuthentication();

(2) 对于web应用,我们不能将authentication object设为null,不要调用

AuthenticationUtil.configureAuthentication(role);
// call to the secured method 

【讨论】:

【参考方案2】:

您可以在当前线程和会话中自己注册一个身份验证令牌(如果在 Web 应用程序中使用):

SecurityContextHolder.getContext().setAuthentication(token);
session.put(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

只要添加适当的角色,您就可以为此使用标准的 UsernamePasswordAuthenticationToken。

【讨论】:

以上是关于Spring Security:在后台任务中调用@PreAuthorize 保护的方法的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章