Spring REST Api——访问存储库中的用户详细信息
Posted
技术标签:
【中文标题】Spring REST Api——访问存储库中的用户详细信息【英文标题】:Spring REST Api -- access User details in repository 【发布时间】:2017-12-29 23:20:49 【问题描述】:RESPApi项目的设置是:
SpringBoot Spring 的 OAuth2在项目中,我们有很多客户端,因此 SQL 查询几乎总是在 where
子句中包含 "... and clientId = ?"
。
我们将clientId
与其他用户详细信息一起存储在SecurityContext
中(我们扩展了Spring 的User
类)。
问题是:如何获取@Repository
中的User
对象?
我们能想到的可能解决方案:
-
在每个存储库实现中添加
SecurityContextHolder.getContext().getAuthentication()
将结果转换为我们的自定义 UserDetails 实现并使用它。
缺点:不知何故,我觉得有更好的解决方案。
-
将
@AuthenticationPrincipal
注解的参数添加到控制器,然后将参数传递给服务层,然后再传递到存储库层。
缺点:通过 2 层参数仅获得clientId
似乎不合理。
我想到了@Repository
类中的@Autowired
参数MyUser user
。第一次尝试是创建@Configuration
注释类,其中将有一个方法
@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,但我觉得一定有更好的方法。
任何想法如何解决这个问题?
【问题讨论】:
【参考方案1】:如果您正在使用Spring Data
(或有时间改用它),您可以在查询中直接使用SecurityEvaluationContextExtension
和principal
:
https://***.com/a/29692158/1777072
如果没有,你可以隐藏静态访问,如果它冒犯了(或者如果你想在未来对它进行更多控制):
@Component
public class AuthenticationHelper
public Authentication getAuthentication()
return SecurityContextHolder.getContext().getAuthentication();
然后将该类注入到您的存储库中。
或您的服务。这可能比存储库更合适。
我喜欢让存储库保持沉默(最终使用 Spring Data 来避免完全编写它们)。
而且我喜欢将服务视为与 Web 层分离,在单独的盒子上运行(即使它们不是)。在这种情况下,您永远不会通过 HTTP 将身份验证详细信息从控制器传递到服务。该服务将为自己获取身份验证详细信息,而不仅仅是信任 Web 层发送的内容。
所以我认为 Service 应该自己获取详细信息,而不是 Controller 传递它们。
【讨论】:
【参考方案2】:您的 bean 为 null,因为默认情况下 bean 是单例的,它们是在应用程序启动时创建的,并且您可以想象,此时您不会有 SecurityContext
。
尝试使用请求范围声明您的 bean,以这种方式:
@Bean
@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.TARGET_CLASS)
public MyUser getUser()
.....
【讨论】:
以上是关于Spring REST Api——访问存储库中的用户详细信息的主要内容,如果未能解决你的问题,请参考以下文章
无法从同一网络中的另一台计算机访问在我的计算机中运行的 SPRING BOOT 应用程序的 REST API
PayPal REST API 为信用卡令牌返回 500 服务器错误