登录用户数据的获取

在 Spring Security 中,用户登录信息本质上还是保存在HttpSession中,但为了方便使用,Spring Security 对HttpSession中的用户信息进行了封装。我们可以通过以下两种思路获取用户登录信息:

  1. 从SecurityContextHolder 中获取。
  2. 从当前请求对象中获取。

无论是哪种获取方式,都离不开Authentication,在Spring Security 中,Authentication 对象主要有两方面功能;

  1. 作为AuthenticationManager 的输入参数,提供用户身份认证的凭证,当它当作一个输入参数时,它的isAuthenticated方法返回的时false,表示用户还未认证。
  2. 代表已经经过身份认证的用户,此时的 Authentication 可以从 SecurityContext 中获取。

Authentication 主要包含三个方面的信息:

  1. principal:定义认证的用户。如果用户使用用户名/密码的方式登录,principal 通常就是一个UserDetails对象。
  2. credentials:登录凭证,一般就是指密码。当用户登录成功之后,登录凭证会被自动移除,以防止泄露。
  3. authorities:用户被授予的权限信息。

SecurityContextHolder

SecurityContextHolder.getContext() 是一个静态方法,也就意味着我们随时随地都可以获取到登录用户信息。如下:

@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/info")public void userInfo(){Authentication authentication = SecurityContextHolder.getContext().getAuthentication();String name = authentication.getName();Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();}
}

SecurityContextHolder 中存储的是SecurityContext ,SecurityContext 中存储的是Authentication,三者关系如下:

SecurityContextHolder 中定义了三种不同的数据存储策略。(典型的策略模式)

  1. MODE_THREADLOCAL :这种存放策略是将SecurityContext 存放在ThreadLocal中,ThreadLocal 的特点是在哪个线程中存储就要在哪个线程中读取。这也是SecurityContextHolder 的默认存储策略,这种存储策略意味着如果在具体的业务处理代码中,开启了子线程,在子线程中去获取登录用户数据,就会获取不到。
  2. MODE_INHERITABLETHREADLOCAL :这种存储模式适合于多线程环境,如果希望在子线程中也能够获取到登录用户的数据,那么可以采用这种存储模式。
  3. MODE_GLOBAL :这种存储模式实际是将数据保存到一个静态变量中,在Web开发中,很少使用。

Spring Security 中定义了SecurityContextHolderStrategy 接口来规范存储策略中的方法,如下:

public interface SecurityContextHolderStrategy {//用来清除存储的SecurityContext 对象void clearContext();//用来获取存储的SecurityContext 对象SecurityContext getContext();//用来设置存储的SecurityContext 对象void setContext(SecurityContext context);//用来创建一个空的SecurityContext 对象SecurityContext createEmptyContext();
}

在SecurityContextHolderStrategy 接口一共有三个实现类,对应三种不同的策略模式,如图:

ThreadLocalSecurityContextHolderStrategy:用ThreadLocal 作为存储数据的载体,所以针对SecurityContext 的清空、获取以及存储,都是在ThreadLocal 中进行操作的。SecurityContext 是一个接口,它只实现了SecurityContextImpl,所以创建就直接新建了一个SecurityContextImpl对象即可。

InheritableThreadLocalSecurityContextHolderStrategy:它和ThreadLocalSecurityContextHolderStrategy 的实现此策略基本一致,不同的是存储数据的载体变了,InheritableThreadLocalSecurityContextHolderStrategy 中是用InheritableThreadLocal ,InheritableThreadLocal继承了ThreadLocal,但是多了一个特性,就是在子线程创建的一瞬间,会自动将父线程中的数据复制到子线程中。正是利用这一特性,实现了子线程中获取用户的登录信息。

GlobalSecurityContextHolderStrategy:它是用一个静态方法来保存SecurityContext,所以它也可以在多线程环境下使用。但是一般在web开发中,这种存储策略使用的较少。

如果我们需要修改存储策略,可以配置VM options参数,如下;

-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL

这样子线程中也能获取到用户的信息了。

Spring Security(五)相关推荐

  1. Spring Security + JWT实现权限管理

    1 写在之前 本博客主要使用Spring Boot 整合Spring Security + JWT实现权限管理,利用JWT工具生成token,返回给登录接口.在访问其他接口时,采用Bearer Tok ...

  2. 【Spring Security】五、自定义过滤器

    在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...

  3. (一)、Spring Security OAuth2 五种授权方式介绍

    更多相关文章请见:Spring Security文章目录 1.简介 OAuth 2.0定义了五种授权方式. RFC规范链接 authorization_code:授权码类型,授权系统针对登录用户下发c ...

  4. Spring Security 5.5发布,正式实装OAuth2.0的第五种授权模式

    今天Spring Security 5.5发布了,主要涉及OAuth2.0和SAML2.0两个协议.其中最大的亮点是支持了OAuth2.0的另一种授权模式jwt-bearer.这个模式可能对大家比较陌 ...

  5. Spring Security 入门(五):在 Spring-Boot中的应用

    前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖  <parent>    <groupId>org.springframework.bo ...

  6. spring boot security 权限用postman测试_Spring Security(五):前后端权限控制详解

    文章回顾: Spring Security(一):整合JWT实现登录功能 Spring Security(二):获取用户权限菜单树 Spring Security(三):与Vue.js整合 Sprin ...

  7. SpringSecurity系列(五) Spring Security 权限设计

    1. 写在前面 权限设计无非就是:用户-角色-菜单,再加上两张中间表. 首先需要给角色赋予权限菜单,然后再把角色赋给相应的用户.比如人事部门主管用户名是hrUser,他的角色是hrRole,角色用有的 ...

  8. Spring Security 详解与实操第五节 JWT和Oauth2

    令牌扩展:如何使用 JWT 实现定制化 Token? 上一讲我们详细介绍了在微服务架构中如何使用 Token 对微服务的访问过程进行权限控制,这里的 Token 是类似"b7c2c7e0-0 ...

  9. Spring Security OAuth2.0认证授权五:用户信息扩展到jwt

    历史文章 [Spring Security OAuth2.0认证授权一:框架搭建和认证测试] [Spring Security OAuth2.0认证授权二:搭建资源服务] [Spring Securi ...

  10. Spring Security实战--(五)认证和鉴权过程

    前面几篇直接讲了Demo,但是可能还是有点混乱,这里再将整个认证过程梳理一下,加深对前面的理解 一.标准的身份验证方案 对一个系统来说,标准的安全身份验证方案应该按如下步骤: 用户使用用户名和密码登录 ...

最新文章

  1. shell自动安装mysql_RPM包安装mysql,采用shell脚本实现自动安装、配置与卸载
  2. Java平台无关性——跨平台
  3. android源码分析之JNI调用与回调
  4. 内核常见锁的机制与实现分析1
  5. 基于Consul的数据库高可用架构【转】
  6. servlet实现新闻控制
  7. Guava学习笔记(1)--安全地使用null(Using and avoiding null)
  8. 三菱PLC连接威纶通触摸屏
  9. java还原混淆代码_飘云阁安全论坛如何还原混淆加密的JAVA代码 - Powered by Discuz!...
  10. Spring Security系列教程27--Spring Security实现CAS单点登录--搭建CAS服务端
  11. 一位技术演讲家的自白
  12. 基于Java Socket的局域网聊天系统
  13. 计算机无纸化考试题库,无纸化考试题库系统
  14. netty报错:LEAK: ByteBuf.release() was not called before it‘s garbage-collected
  15. 使用Python绘制词云图片
  16. 如何制作Chrome扩展?<详细教程>
  17. 风过,摔死一只ofo小黄猪
  18. 查看mysql数据库的定时任务_mysql数据库的定时任务
  19. 计算机防火墙有用吗,win7自带防火墙有用吗
  20. 3.6 函数作图与渐近线

热门文章

  1. arcgis 添加excel站点数据时,提示没有注册类
  2. 程序员的成长故事之 五年技术之路
  3. java实现区域生长算法_改进的种子区域生长算法
  4. markov 模型概述
  5. md 文件的常用编辑介绍
  6. 从七岁到二十七岁的二十年
  7. 【LOJ#570】Misaka Network 与任务
  8. TLS/SSL 协议详解(6) SSL 数字证书的一些细节1 证书验证
  9. Nginx高可用配置
  10. 全网真正解决百度定位只定位一次的问题(亲测有效)