Spring Security(五)
登录用户数据的获取
在 Spring Security 中,用户登录信息本质上还是保存在HttpSession中,但为了方便使用,Spring Security 对HttpSession中的用户信息进行了封装。我们可以通过以下两种思路获取用户登录信息:
- 从SecurityContextHolder 中获取。
- 从当前请求对象中获取。
无论是哪种获取方式,都离不开Authentication,在Spring Security 中,Authentication 对象主要有两方面功能;
- 作为AuthenticationManager 的输入参数,提供用户身份认证的凭证,当它当作一个输入参数时,它的isAuthenticated方法返回的时false,表示用户还未认证。
- 代表已经经过身份认证的用户,此时的 Authentication 可以从 SecurityContext 中获取。
Authentication 主要包含三个方面的信息:
- principal:定义认证的用户。如果用户使用用户名/密码的方式登录,principal 通常就是一个UserDetails对象。
- credentials:登录凭证,一般就是指密码。当用户登录成功之后,登录凭证会被自动移除,以防止泄露。
- 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 中定义了三种不同的数据存储策略。(典型的策略模式)
- MODE_THREADLOCAL :这种存放策略是将SecurityContext 存放在ThreadLocal中,ThreadLocal 的特点是在哪个线程中存储就要在哪个线程中读取。这也是SecurityContextHolder 的默认存储策略,这种存储策略意味着如果在具体的业务处理代码中,开启了子线程,在子线程中去获取登录用户数据,就会获取不到。
- MODE_INHERITABLETHREADLOCAL :这种存储模式适合于多线程环境,如果希望在子线程中也能够获取到登录用户的数据,那么可以采用这种存储模式。
- 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(五)相关推荐
- Spring Security + JWT实现权限管理
1 写在之前 本博客主要使用Spring Boot 整合Spring Security + JWT实现权限管理,利用JWT工具生成token,返回给登录接口.在访问其他接口时,采用Bearer Tok ...
- 【Spring Security】五、自定义过滤器
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- (一)、Spring Security OAuth2 五种授权方式介绍
更多相关文章请见:Spring Security文章目录 1.简介 OAuth 2.0定义了五种授权方式. RFC规范链接 authorization_code:授权码类型,授权系统针对登录用户下发c ...
- Spring Security 5.5发布,正式实装OAuth2.0的第五种授权模式
今天Spring Security 5.5发布了,主要涉及OAuth2.0和SAML2.0两个协议.其中最大的亮点是支持了OAuth2.0的另一种授权模式jwt-bearer.这个模式可能对大家比较陌 ...
- Spring Security 入门(五):在 Spring-Boot中的应用
前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖 <parent> <groupId>org.springframework.bo ...
- spring boot security 权限用postman测试_Spring Security(五):前后端权限控制详解
文章回顾: Spring Security(一):整合JWT实现登录功能 Spring Security(二):获取用户权限菜单树 Spring Security(三):与Vue.js整合 Sprin ...
- SpringSecurity系列(五) Spring Security 权限设计
1. 写在前面 权限设计无非就是:用户-角色-菜单,再加上两张中间表. 首先需要给角色赋予权限菜单,然后再把角色赋给相应的用户.比如人事部门主管用户名是hrUser,他的角色是hrRole,角色用有的 ...
- Spring Security 详解与实操第五节 JWT和Oauth2
令牌扩展:如何使用 JWT 实现定制化 Token? 上一讲我们详细介绍了在微服务架构中如何使用 Token 对微服务的访问过程进行权限控制,这里的 Token 是类似"b7c2c7e0-0 ...
- Spring Security OAuth2.0认证授权五:用户信息扩展到jwt
历史文章 [Spring Security OAuth2.0认证授权一:框架搭建和认证测试] [Spring Security OAuth2.0认证授权二:搭建资源服务] [Spring Securi ...
- Spring Security实战--(五)认证和鉴权过程
前面几篇直接讲了Demo,但是可能还是有点混乱,这里再将整个认证过程梳理一下,加深对前面的理解 一.标准的身份验证方案 对一个系统来说,标准的安全身份验证方案应该按如下步骤: 用户使用用户名和密码登录 ...
最新文章
- shell自动安装mysql_RPM包安装mysql,采用shell脚本实现自动安装、配置与卸载
- Java平台无关性——跨平台
- android源码分析之JNI调用与回调
- 内核常见锁的机制与实现分析1
- 基于Consul的数据库高可用架构【转】
- servlet实现新闻控制
- Guava学习笔记(1)--安全地使用null(Using and avoiding null)
- 三菱PLC连接威纶通触摸屏
- java还原混淆代码_飘云阁安全论坛如何还原混淆加密的JAVA代码 - Powered by Discuz!...
- Spring Security系列教程27--Spring Security实现CAS单点登录--搭建CAS服务端
- 一位技术演讲家的自白
- 基于Java Socket的局域网聊天系统
- 计算机无纸化考试题库,无纸化考试题库系统
- netty报错:LEAK: ByteBuf.release() was not called before it‘s garbage-collected
- 使用Python绘制词云图片
- 如何制作Chrome扩展?<详细教程>
- 风过,摔死一只ofo小黄猪
- 查看mysql数据库的定时任务_mysql数据库的定时任务
- 计算机防火墙有用吗,win7自带防火墙有用吗
- 3.6 函数作图与渐近线