如何在实现 Spring Data JPA AuditorAware 接口时获取 getUserPrincipal().getUserName()

Posted

技术标签:

【中文标题】如何在实现 Spring Data JPA AuditorAware 接口时获取 getUserPrincipal().getUserName()【英文标题】:How to obtain getUserPrincipal().getUserName() while implementing Spring Data JPA AuditorAware interface 【发布时间】:2014-10-17 16:12:36 【问题描述】:

我正在尝试在我当前的项目中使用 Spring Data JPA (1.6.2)。一切似乎都运行良好,但我在实现 AuditorAware 接口时卡住了。

我的应用程序将部署到旧的 Apache Jetspeed JSR168 兼容门户。该门户负责用户身份验证/授权。因此,我不必使用像 Spring Security 或 Shiro 这样的安全框架。我的应用程序中的其他框架是:

    Struts 1.2.4(带有 Struts-Portal-Bridge) 春季 3.2.10 JPA(Hibernate 3.6.10 作为 ORM 提供者)

我想在我的实体中使用 @CreatedBy 和 @LastModifiedBy 注释字段(我得到了 @CreatedDate 和 @LastModifiedDate 工作)。在我的应用程序中,我通常使用 request.getUserPrincipal().getUserName() 获取用户名。

但是在实现 AuditorAware 接口时如何获取用户名?

来自Spring Data JPA docs的示例实现:

class SpringSecurityAuditorAware implements AuditorAware<User> 

    public User getCurrentAuditor() 

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication == null || !authentication.isAuthenticated()) 
            return null;
        

        return ((MyUserDetails) authentication.getPrincipal()).getUser();
    

不知何故,我想像这样实现 AuditorAware:

class MyAuditorAware implements AuditorAware<String> 
    public String getCurrentAuditor() 
        return <<principal from servlet- or portletcontext>>.getUserName();
    

如何在不添加额外框架的情况下完成此操作?

【问题讨论】:

有一个肮脏的把戏——在你的 servlet/portlet 请求处理的最开始就在某种静态持有者类中捕获你的用户主体,然​​后在你的 auditaware 中调用持有者获取器 【参考方案1】:

正如 Konstantin 在他的评论中已经提到的,您可能希望将主体名称保存在适合请求的范围内。这很可能是ThreadLocal。这使您以后可以在 AuditorAware 实现中轻松获得它。

为了保持 Spring 的命名,将其命名为 PrincipalContextHolder。作为起点,您可以查看JodaTimeContextHolder 的源代码,了解ContextHolder 的简单实现。

【讨论】:

以上是关于如何在实现 Spring Data JPA AuditorAware 接口时获取 getUserPrincipal().getUserName()的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data Jpa如何实现审计和乐观锁功能

Spring Data Jpa如何实现审计和乐观锁功能

spring data jpa

在Spring Boot中使用Spring-data-jpa实现分页查询(转)

使用Spring Data JPA的Spring Boot

Spring整合Hibernate实现Spring Data JPA