Spring 安全表达式:"authenticated" 与 "isAuthenticated()"

Spring Security Expression: "authenticated" vs. "isAuthenticated()"

根据Spring Security docs,检查用户是否通过身份验证的表达式是isAuthenticated()。例如,我们会做 @PreAuthorize("isAuthenticated()")

不过,根据official example和我自己的测试确认,@PreAuthorize("authenticated")也可以。

它是 Spring 安全功能还是仅仅是 Java 功能(例如 authenticated 是支持 getter isAuthenticated() 某处的字段)这使得 authenticated 也能正常工作?

我查看了org.springframework.security.web.servletapi.Servlet3SecurityContextHolderAwareRequestWrapper中的源代码:

private boolean isAuthenticated() {
    return getUserPrincipal() != null;
}

然后查看 getUserPrincipal():

@Override
public Principal getUserPrincipal() {
    Authentication auth = getAuthentication();
    if ((auth == null) || (auth.getPrincipal() == null)) {
        return null;
    }
    return auth;
}

然后 getAuthentication()。这是关键点:

private Authentication getAuthentication() {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();//!!!
    return (!this.trustResolver.isAnonymous(auth)) ? auth : null;
}

如图所示,authentication 对象由 SecurityContextHolder 管理。

至于authenticated,我认为它可能是spring bean容器中的单例Java bean。它具有与以下相同的值:

authentication.isAuthenticated();

org.springframework.security.core.Authentication

@PreAuthorize 的值是一个 SpEL ,根据 docs ,它将根据根对象 SecurityExpressionRoot.

求值

isAuthenticated() 是在 SecurityExpressionRoot 实例上调用 isAuthenticated() 的语法(参见 this)。

authenticated 是访问 SecurityExpressionRoot 实例属性的语法(参见 this)。它将尝试调用以下 public 属性 或方法来计算值:

  • authenticated 属性
  • getAuthenticated()
  • isAuthenticated()(仅当评估值为布尔值时)
  • authenticated()

您可以在 here 的代码中找到这样的逻辑。