8

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

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

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

AuthenticationCredentialsNotFoundException:在 SecurityContext 中找不到 Authentication 对象

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

  1. 为后台任务编写一些自定义 AuthenticationToken。
  2. 将 UsernamePasswordAuthenticationToken 与假用户一起使用。
  3. 不要在后台任务中使用安全方法。
  4. 还有其他建议吗?

什么是正确的方法?

4

2 回答 2

2

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

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

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

于 2012-04-26T11:13:56.893 回答
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);
}

所以它看起来像

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

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

AuthenticationUtil.configureAuthentication(role);
// call to the secured method 
于 2019-09-25T15:01:11.827 回答