当前位置: 首页 > 知识库问答 >
问题:

使用Spring Security的静态方法获取当前用户详细信息

陶征
2023-03-14

我需要获得当前用户的详细信息。要获得详细信息,我们可以使用SecurityContextHolder。getContext()并提取详细信息。根据

SecurityContextHolder、SecurityContext和身份验证对象

默认情况下,SecurityContextHolder使用ThreadLocal来存储这些详细信息,这意味着安全上下文始终可用于同一执行线程中的方法。如果在处理当前主体的请求后注意清除线程,以这种方式使用ThreadLocal是非常安全的。当然,Spring Security会自动为您处理这一点,因此无需担心。

在请求之间存储SecurityContext

在Spring Security中,在请求之间存储SecurityContext的责任属于SecurityContextPersistenceFilter,默认情况下,它将上下文存储为HTTP请求之间的HttpSession属性。对于每个请求,它将上下文恢复到SecurityContextHolder,最重要的是,在请求完成时清除SecurityContextHolder

许多其他类型的应用程序(例如,无状态RESTful Web服务)不使用HTTP会话,并且会对每个请求进行重新身份验证。但是,链中包含SecurityContextPeristenceFilter仍然很重要,以确保在每次请求后清除SecurityContextHolder

问题是

我需要服务层多个位置的用户详细信息来返回基于用户权限的信息,因此我们有一个静态方法来返回这些详细信息。该项目由REST API和会话创建策略组成,如SessionCreationPolicy。无状态SecurityContextHolderStrategy作为ThreadLocal。服务层由@Transactional组成。

现在考虑对API的多个并发请求,

  • Spring Security将如何管理无状态应用程序的SecurityContextPersistenceFilter,是否需要手动配置
  • 使用SecurityContextHolderStrategy作为ThreadLocal可以吗
  • 由于ThreadLocal策略和静态方法,是否有可能获得错误/无效的用户详细信息

环境:

框架:Spring Boot
ORM:Hibernate
html" target="_blank">数据库:Postgres
体系结构:单片(即将迁移到微服务)

如果需要,我会补充更多细节

更新:

如前所述,感谢@Macro提供SessionCreationPolicy。无状态

SessionManagementConfigrerisStatless()方法组成,对于无状态策略返回true。基于该超文本传输协议,使用NullSecurityContextRepository和请求缓存NullRequestCache设置共享对象。因此,在HttpSessionSecurityContextRepository中不会有任何值可用。因此,使用静态方法的用户可能不会出现无效/错误详细信息的问题

  • SecurityContextHolderStrategy是否对MODE_INHERITABLETHREADLOCAL的用户详细信息有任何影响,MODE_THREADLOCAL没有值将设置为具有HttpSessionSecurityContextRepository的共享对象?

代码:

        if (stateless) {
            http.setSharedObject(SecurityContextRepository.class,
                    new NullSecurityContextRepository());
        }

        if (stateless) {
            http.setSharedObject(RequestCache.class, new NullRequestCache());
        }

代码:

获取用户详细信息的静态方法

    public static Optional<String> getCurrentUserLogin() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return Optional.ofNullable(extractPrincipal(securityContext.getAuthentication()));
    }

    private static String extractPrincipal(Authentication authentication) {
        if (authentication == null) {
            return null;
        } else if (authentication.getPrincipal() instanceof UserDetails) {
            UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
            return springSecurityUser.getUsername();
        } else if (authentication.getPrincipal() instanceof String) {
            return (String) authentication.getPrincipal();
        }
        return null;
    }


    public static Optional<Authentication> getAuthenticatedCurrentUser() {
        log.debug("Request to get authentication for current user");
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return Optional.ofNullable(securityContext.getAuthentication());
    }

会话管理

.sessionManagement()
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

笔记

SecurityContextHolderStrategy asThreadLocal

服务层由@Transactional组成。

共有1个答案

澹台俊材
2023-03-14

背景

.sessionManagement()
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

将使用NullSecurityContextRepository而不是默认的HttpSessionSecurityContextRepository导致Spring Security。

这是一个简单的实现,因为它不会将任何内容保存到HTTP会话中,并且对于每个请求,都会创建一个全新的空SecurityContext,因此没有存储的身份验证等。

那么,回答你的第一个问题:

SecurityContextPeristenceFilter将与HttpSessionRepository一样工作,无需其他手动配置。

回答你的第二和第三个问题,关于当地人。

是的,这就是使用它们的全部意义,而且这是默认策略。因此,每个线程都有自己的SecurityContext/身份验证对象。您正在使用静态方法访问ThreadLocal,因此不可能访问“错误”的用户详细信息。在您的用例中使用“GlocalSecurityContextHolderStrategy”可能会有问题,但无论如何,这不是您要做的。

此外,请记住,所有这些都与@Transactionals无关。

 类似资料:
  • 本文向大家介绍oracle获取当前用户表、字段等详细信息SQL,包括了oracle获取当前用户表、字段等详细信息SQL的使用技巧和注意事项,需要的朋友参考一下 做个笔记,仅供参考 备注:user_开头是当前用户,all_开头所有用户,dba_开头包括系统表

  • 本文向大家介绍DB2获取当前用户表、字段、索引等详细信息,包括了DB2获取当前用户表、字段、索引等详细信息的使用技巧和注意事项,需要的朋友参考一下  获取所有表、字段、索引等详细信息

  • 目前,我正在使用以下内容将用户登录到我的应用程序中。然而,我想使用一个角函数来实际执行登录。为此,我想创建一个Rest网络服务来进行身份验证,但是我在SO上看到的所有示例都使用我认为被贬低的用户。我还希望该服务返回有关用户的信息。 我要问的是如何将MyUserDetailsService更改为用作登录的restful服务,或者如何创建一个可用于登录的服务,该服务将在登录后返回用户对象。 这是我的a

  • Amazon标识管理iam=Amazon标识管理客户端Builder.standard()。US_EAST_1)。 有人能告诉我怎么做吗? 我试图在下面的程序中列出一个用户的标签,但我得到了下面的错误:我们计算的请求签名与您提供的签名不匹配。检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅维修文档。 公共类ListUserTags{ }

  • 接口说明 获取当前登录用户的信息 如需调用,请访问 开发者文档 来查看详细的接口使用说明 该接口仅开放给已获取SDK的开发者 API地址 GET /usercenter/api/userinfo/v1.0.0/getLoginUserInfo 是否需要登录 是 请求字段说明 参数 类型 请求类型 是否必须 说明 token string header 是 当前登录用户的TOKEN 响应字段说明 参