1. 简介
     1) SecurityContextHolder是SpringSecurity最基本的组件了,是用来存放SecurityContext的对象,默认是使用ThreadLocal实现的,这样就保证了本线程内所有的方法都可以获得SecurityContext对象。
     2) SecurityContextHolder还有其他两种模式,分别为SecurityContextHolder.MODE_GLOBAL和SecurityContextHolder.MODE_INHERITABLETHREADLOCAL,前者表示SecurityContextHolder对象
         的全局的,应用中所有线程都可以访问;后者用于线程有父子关系的情境中,线程希望自己的子线程和自己有相同的安全性。
     3)大部分情况下我们不需要修改默认的配置,ThreadLocal是最常用也是最合适大部分应用的。
  2. 使用SecurityContextHolder获取当前登录的用户信息
    SecurityContextHolder中保存的是当前访问者的信息。Spring Security使用一个Authentication对象来表示这个信息。一般情况下,我们都不需要创建这个对象,在登录过程中,Spring Security已经创建了该对象并帮我们放到了SecurityContextHolder中。从SecurityContextHolder中获取这个对象也是很简单的。比如,获取当前登录用户的用户名,可以这样 :

    
    // 获取安全上下文对象,就是那个保存在 ThreadLocal 里面的安全上下文对象
    // 总是不为null(如果不存在,则创建一个authentication属性为null的empty安全上下文对象)
    SecurityContext securityContext = SecurityContextHolder.getContext();// 获取当前认证了的 principal(当事人),或者 request token (令牌)
    // 如果没有认证,会是 null,该例子是认证之后的情况
    Authentication authentication = securityContext.getAuthentication()// 获取当事人信息对象,返回结果是 Object 类型,但实际上可以是应用程序自定义的带有更多应用相关信息的某个类型。
    // 很多情况下,该对象是 Spring Security 核心接口 UserDetails 的一个实现类,你可以把 UserDetails 想像
    // 成我们数据库中保存的一个用户信息到 SecurityContextHolder 中 Spring Security 需要的用户信息格式的
    // 一个适配器。
    Object principal = authentication.getPrincipal();
    if (principal instanceof UserDetails) {String username = ((UserDetails)principal).getUsername();
    } else {String username = principal.toString();
    }
  3. 修改SecurityContextHolder的工作模式
     综上所述,SecurityContextHolder可以工作在以下三种模式之一:
     1)MODE_THREADLOCAL (缺省工作模式)
     2)MODE_GLOBAL
     3)  MODE_INHERITABLETHREADLOCAL
     4) 修改SecurityContextHolder的工作模式有两种方法 :
             a: 设置一个系统属性(system.properties) : spring.security.strategy;
                  SecurityContextHolder会自动从该系统属性中尝试获取被设定的工作模式
             b:  调用SecurityContextHolder静态方法setStrategyName()
         
    程序化方式主动设置工作模式的方法     

  4. SecurityContextHolder存储SecurityContext的方式(默认就是mode_threadlocal)
     
    1)单机系统,即应用从开启到关闭的整个生命周期只有一个用户在使用。由于整个应用只需要保存一个SecurityContext(安全上下文即可)
     2)多用户系统,比如典型的Web系统,整个生命周期可能同时有多个用户在使用。这时候应用需要保存多个SecurityContext(安全上下文),需要利用ThreadLocal进行保存,每个线程都可以利用ThreadLocal获取其自己的SecurityContext,及安全上下文。

  5. 比如我们使用jwt实现登录功能的时候,我们可以将用户信息保存在安全上下文中

     @Overridepublic String login(String username, String password) {String token = null;//密码需要客户端加密后传递try {UserDetails userDetails = loadUserByUsername(username);if(!password.equals(BasicEncryptUtils.decryptByRSA(userDetails.getPassword()))){throw new ServiceException("password.is.not.correct", ResultCode.VALIDATE_FAILED.getCode());}//根据userDetails构建新的AuthenticationUsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());//存放authentication到SecurityContextHolderSecurityContextHolder.getContext().setAuthentication(authentication);//使用jwt生成tokentoken = jwtTokenUtil.generateToken(userDetails, RsaUtils.getPrivateKey(propertiesUtils.getPrivateKeyUrl()));//到redis中查看该账号是否之前已经登录if (redisUtil.getValueByKey(CommonConstant.ormis_online_login_user_info+username)!=null){//删掉对应的数据redisUtil.deleteCache(CommonConstant.ormis_online_login_user_info+username);}//重新存储redisUtil.set(CommonConstant.ormis_online_login_user_info+username,token,propertiesUtils.getExpiration());} catch (Exception e) {log.error("login error is {}", e.getMessage());throw new ServiceException(e.getMessage(), ResultCode.VALIDATE_FAILED.getCode());}return token;}

    由上面代码可以发现我们获取用户的信息之后,通过SecurityContextHolder.getContext().setAuthentication(authentication);方式将用户相关的信息存放到系统的安全上下文中,并且由于 SecurityContextHolder默认是mode_threadlocal模式,那么会将所有登录的用户信息都保存,每个登录的用户都可以通过SecurityContextHolder.getContext().getAuthentication();方式获取
    当前自己保存的用户信息

安全认证之SecurityContextHolder相关推荐

  1. Spring Security 实战:使用 JWT 认证访问接口

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 1. 前言 欢迎阅读Spring Security 实战 ...

  2. java 用户登录token_Java,SpringBoot采用token方式实现登录认证

    IT小奋斗2021-01-13 21:48:33 Token,令牌,访问资源的凭证,每次访问带上这个令牌,就可识别出用户身份. JWT (JsonWebToken),是实现token技术的一种解决方案 ...

  3. Spring Security 认证执行流程

    本文基于 Spring Security 5.x 推荐阅读: 项目集成Spring Security SpringSecurity 整合 JWT 一.外层-正常登陆调用 项目启动后会自动寻找 User ...

  4. 项目1在线交流平台-7.构建安全高效的企业服务-2.使用Security自定义社区网页认证与授权

    文章目录 功能需求 一. 废弃登录检查的拦截器 二.授权配置 1. 导包 2. Security配置 2.1 `WebSecurity` 2.2`HttpSecurity` ` http.author ...

  5. 傻瓜式使用SpringSecurity完成前后端分离+JWT+登录认证+权限控制

    流程分析 流程说明: 客户端发起一个请求,进入 Security 过滤器链.当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 ...

  6. Spring Security 源码分析:Spring Security 授权过程

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring I ...

  7. SpringBoot使用security和jwt进行鉴权设计

    一.使用security默认登录接口登录成功.生成token.返回前段 项目的结构如下: 1.引入jar包 <dependency><groupId>org.springfra ...

  8. 整合Spring Security

    很多人不懂spring security,觉得这个框架比shiro要难,的确,security更加复杂一点,同时功能也更加强大,我们首先来看一下security的原理 上面这张图一定要好好看,特别清晰 ...

  9. Spring Security(一):最简单的Spring Security程序

    一:简介 权限管理常用的有Apache Shiro和Spring Security, Apache Shiro简单易用,Spring Security集成复杂,但功能强大,可以与Spring的其它框架 ...

最新文章

  1. Python告诉你这些旅游景点好玩、便宜、人又少!
  2. 支付宝技术风险负责人陈亮:把事情做到极致,技术的差异性才会体现出来
  3. InsightFace及其mxnet、tensorflow代码实现
  4. ListView列表刷新方法的区别
  5. python webdriver脚本例子_Selenium webdriver添加cookie实现过程详解
  6. android自动发送dtmf,Android发送dtmf键盘事件(模拟通话界面键盘事件)
  7. pion webrtc 示例代码解析 一
  8. 访问修饰符 public private protected default
  9. 7.这就是搜索引擎:核心技术详解 --- 云存储与云计算
  10. 说一说javascript跨域和jsonp
  11. 给物体赋值 只改变transform.position的某一维,访问另一个脚本的变量以及给物体用脚本动态添加属性
  12. 计划学Linux,老男孩Linux怎么样?真实的学员评价!
  13. win10wifi开关自动弹回_win10突然搜不到wifi了,这个开关点不动,点了会自动变回去...
  14. ajax 后面接什么,什么是AJAX?
  15. [EKL-踩坑记] —— ES虚拟内存设置
  16. Vue基础入门(2) Vue.js下载与安装
  17. 以太网接口 数据采集 matlab,基于以太网接口并行多通道采集器的设计
  18. 数据结构与算法——23. 用嵌套列表与链表实现树结构
  19. 互联网快讯:瑞幸回应价格异常;极米H3S、极米Z6X Pro受用户青睐;知网回应被中科院停用
  20. 《python数据分析与挖掘》-步骤

热门文章

  1. 如何取消加密的pdf文件密码?
  2. 生成带参数的太阳码,遇到41030问题
  3. 目标检测~无人机视角
  4. ASP中LIKE模糊查
  5. flutterapp部分手机无法打开_无法运行啊 · Issue #4 · shichunlei/flutter_app · GitHub
  6. YOLO系列梳理(三)YOLOv5
  7. CentOS7卸载及安装MySQL5.7
  8. (二)从生物神经元来学习人工神经元基本模型的工作原理
  9. Google趋势VS百度指数
  10. Hibernate中发生Session is closed 的另一种可能