Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用具有Spring安全性的静态方法获取当前用户详细信息_Java_Spring_Spring Boot_Spring Security_Static - Fatal编程技术网

Java 使用具有Spring安全性的静态方法获取当前用户详细信息

Java 使用具有Spring安全性的静态方法获取当前用户详细信息,java,spring,spring-boot,spring-security,static,Java,Spring,Spring Boot,Spring Security,Static,我需要获得当前用户的详细信息,该用户已登录。要获取详细信息,我们可以使用SecurityContextHolder.getContext()并提取详细信息。根据, 默认情况下,SecurityContextHolder使用ThreadLocal存储这些详细信息,这意味着安全上下文始终可用于同一执行线程中的方法。如果在处理当前主体的请求后小心地清除线程,则以这种方式使用ThreadLocal是非常安全的。当然,SpringSecurity会自动为您处理这些问题,因此不必担心 在Spring

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


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


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

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


问题是

    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());
    }
我需要服务层多个位置的用户详细信息来返回基于用户权限的信息,因此我们有一个静态方法来返回这些详细信息。该项目由REST API和会话创建策略组成,如
SessionCreationPolicy.STATELESS
SecurityContextHolderStrategy
作为
ThreadLocal
。服务层由
@Transactional
组成

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

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

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

如果需要,我将添加更多详细信息


更新:

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

        if (stateless) {
            http.setSharedObject(RequestCache.class, new NullRequestCache());
        }
如前所述,感谢@Macro提供的
SessionCreationPolicy.STATELESS

SessionManagementConfigurer
isStateless()
方法组成,该方法对于无状态策略返回true。基于该http,将共享对象设置为
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());
        }

代码:

        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());
    }
注释

    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());
    }
SecurityContextHolderStrategy as
ThreadLocal

服务层由
@Transactional
组成

设置

.sessionManagement()
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
将使用
NullSecurityContextRepository
而不是默认的
HttpSessionSecurityContextRepository
实现Spring安全性

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

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

SecurityContextPersistenceFilter将与 HttpSessionRepository,不需要其他手动配置

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

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

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