Spring REST Api -- 访问存储库中的用户详细信息

Spring REST Api -- access User details in repository

RESPApi 项目的设置是:

在项目中我们有很多客户,所以 SQL 查询几乎总是在 where 子句中有 "... and clientId = ?"

我们将 clientId 与其他用户详细信息一起存储在 SecurityContext 中(我们扩展了 Spring 的 User class)。

问题是:如何获取@Repository中的User对象?

我们能想到的可能解决方案:

  1. 在每个存储库实现中添加

SecurityContextHolder.getContext().getAuthentication()

将结果转换为我们自定义的 UserDetails 实现并使用它。

缺点:不知何故我觉得有更好的解决方案。

  1. @AuthenticationPrincipal注解参数添加到控制器,然后将参数传递给服务层,然后传递给存储层。

缺点:仅通过 2 层传递参数以获得 clientId 似乎不合理。

我在@Repositoryclass中考虑了@Autowired参数MyUser user。第一次尝试是创建 @Configuration 注释 class ,其中将有一个方法

    @Bean
public MyUser getUser() {
    SecurityContext context = SecurityContextHolder.getContext();
    if (context != null) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            return (MyUser) authentication.getPrincipal();
        }
    }
    return null;
}

但是这个bean是空的,我不能使用它。

现在我们已经得到了解决方案 nr 1,但我觉得一定有更好的方法。

有什么解决这个问题的想法吗?

如果您正在使用 Spring Data(或有时间切换到使用它),您可以使用 SecurityEvaluationContextExtension 并在查询中直接使用 principal

如果没有,您可以隐藏静态访问,如果它冒犯了(或者如果您希望在将来对其进行更多控制):

@Component
public class AuthenticationHelper {
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }
}

然后将 class 注入您的存储库。

或您的服务。这可能比存储库更合适。

我喜欢让存储库保持愚蠢(最终使用 Spring 数据来避免完全写入它们)。

而且我喜欢将服务视为从 Web 层中分离出来,运行 在单独的盒子上(即使它们不是)。在那种情况下,您永远不会通过 HTTP 将身份验证详细信息从控制器传递到服务。该服务将为自己获取身份验证详细信息,而不仅仅是信任 Web 层发送给它的内容。

所以我认为服务应该自己获取详细信息,而不是控制器传递它们。

你的 bean 是空的,因为默认情况下 bean 是单例的,它们是在应用程序启动时创建的,你可以想象,那时你不会有 SecurityContext

尝试以这种方式声明具有请求范围的 bean:

@Bean
@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.TARGET_CLASS)
public MyUser getUser() {
   .....
}