服装网站源码php,建设厅网站合同备案在哪里,wordpress 登陆函数,wordpress调用站点标题一、SecurityContextHolder 是什么 SecurityContextHolder用来获取登录之后用户信息。Spring Security 会将登录用户数据保存在Session中。但是#xff0c;为了使用方便,Spring Security在此基础上还做了一些改进#xff0c;其中最主要的一个变化就是线程绑定。当用户登录成功…一、SecurityContextHolder 是什么 SecurityContextHolder用来获取登录之后用户信息。Spring Security 会将登录用户数据保存在Session中。但是为了使用方便,Spring Security在此基础上还做了一些改进其中最主要的一个变化就是线程绑定。当用户登录成功后Spring Security 会将登录成功的用户信息份存到 SecuritvContextHolder 中。SecurityContextHolder 中的数据保存默认是通过ThreadLoca来实现的使用 ThreadLocal 创建的变量只能被当前线程访问不能被其他线程访问和修改也就是用户数据和请求线程绑定在一起。当登录请求处理完毕后Spring Security 会将SecurityContextHolder 中的数据拿出来保存到 Session 中同时将 SecurityContexHolder中的数据清空。以后每当有请求到来时Spring Security 就会先从 Session 中取出用户登录数据保存到 SecuritvContextHolder 中方便在该请求的后续处理过程中使用同时在请求结束时将 SecurityContextHolder 中的数据拿出来保存到 Session 中然后将 SecuritySecurityContextHolder 中的数据清空。这一策略非常方便用户在 Controller、Service 层以及任何代码中获取当前登录用户数据。是一个安全的上下文对象用于获取身份验证通过的用户信息 二、SecurityContextHolder 是何时被创建的 当我们经过表单UsernamePasswordAuthenticationFilter 过滤器后会回调父类的AbstractAuthenticationProcessingFilter父类的AbstractAuthenticationProcessingFilter 是一个过滤器那么肯定有 filter doFilter 方法进到里面后看到认证成功后会调用successfulAuthentication 方法最终看到SecurityContextHolder 被创建成功 2.1 源码实现 2.2 官方文档说明 三、通过SecurityContextHolder 如何获取认证后的用户信息 通过源码得知当我们登录成功后通过SecurityContextHolder.create后放置进去的那么我们也可以通过get 获取到 3.1 官方文档指导如何获取 3.2 代码获取实战
/*** 获取用户信息* return*/RequestMapping(getUserInf.do)ResponseBodypublic String getUserInf() {SecurityContext context SecurityContextHolder.getContext();Authentication authentication context.getAuthentication();System.out.println(authentication);try {String s new ObjectMapper().writeValueAsString(authentication);return s;} catch (JsonProcessingException e) {e.printStackTrace();}return err;
}
3.3 日志打印结果 四、web 前端获取认证后的信息通过(thymeleaf) 有时候我们想通过前端标签判断用户有哪些权限或者角色类似于shiro 标签那种实际上springsecurity 也有 4.1 导入pom依赖 dependency groupIdorg.thymeleaf.extras/groupId artifactIdthymeleaf-extras-springsecurity5/artifactId /dependency 4.2 html 标签加上命名空间 html xmlnshttp://www.w3.org/1999/xhtml xmlns:thhttp://www.thymeleaf.org xmlns:sechttp://www.thymeleaf.org/thymeleaf-extrasspringsecurity5 div classcontainerh1 获取用户信息通过标签/h1!--获取认证用户名--ulli sec:authenticationprincipal.username/lili sec:authenticationprincipal.authorities/lili sec:authenticationprincipal.accountNonExpired/lili sec:authenticationprincipal.accountNonLocked/lili sec:authenticationprincipal.credentialsNonExpired/li/ulbrh1 获取用户权限信息通过标签/h1!--如果没认证--div sec:authorize!isAuthenticated()显示没认证的内容/div!--如果认证了--div sec:authorizeisAuthenticated()显示认证的内容/div通过权限判断button sec:authorizehasAuthority(/insert)新增/buttonbutton sec:authorizehasAuthority(/delete)删除/buttonbutton sec:authorizehasAuthority(/update)修改/buttonbutton sec:authorizehasAuthority(/select)查看/buttonbr/通过角色判断button sec:authorizehasRole(admin)新增/buttonbutton sec:authorizehasRole(admin)删除/buttonbutton sec:authorizehasRole(admin)修改/buttonbutton sec:authorizehasRole(admin)查看/button/div
4.3 测试后效果 我们给当前用户配置了一个 admin的角色没有配置任何权限最终效果页面权限一个都没有显示出来后面配置了角色 admin 的 对应的四个button按钮就出来了也就是达到了我们的效果 五、如果我开启了一个子线程是否还可以获取到认证信息呢 在实际后端开发中有可能在主方法中开启了一个新的线程去获取其他信息但是新线程里面也去获取了这个 SecurityContextHolder.getContext(); 那么肯定是获取不到的因为我们看到SecurityContextHolder 的源码得知默认的策略模式是 threadlocal 模式 5.1 代码测试 RequestMapping(index.page)public String index() {SecurityContext context SecurityContextHolder.getContext();Authentication authentication context.getAuthentication();System.out.println(我是主线程的用户信息authentication);new Thread(() - {SecurityContext context1 SecurityContextHolder.getContext();System.out.println(我是子线程的信息context1.getAuthentication());}).start();return userinf;
}
5.2 日志打印结果 我们可以看到子线程里面获取到的是一个空那么有没有办法在子线程里面也获取到呢其实是有的可以手动将这个认证的对象传到子线程里面去或者通过 在开启子线程的时候通过 SecurityContextHolder.getContext().setAuthentication() 但是这种方式太不优雅了其实我们看看源码是可以更改策略就能实现的 5.3 SecurityContextHolder 源码 我们看到有四个策略 MODE_THREADLOCAL 基于 threadLocal 实现默认就是这个策略 MODE_INHERITABLETHREADLOCAL 基于inheritablethreadlocal 实现他是将主线程值拷贝到子线程一份jdk 自带 MODE_GLOBAL 全局的一个静态变量很少用 MODE_PRE_INITIALIZED 用的少 5.4 自定义策略使用子线程也可以获取到认证信息 我们看到 String SYSTEM_PROPERTY spring.security.strategy; 是一个系统变量参数那么我们可以在启动时候加上参数 -Dspring.security.strategyMODE_INHERITABLETHREADLOCAL 再来测试 最终我们看到在子线程中也能获取到认证后的信息了