前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >在 request 之间共享 SecurityContext

在 request 之间共享 SecurityContext

作者头像
johnhuster的分享
发布2022-03-28 19:06:56
发布2022-03-28 19:06:56
84600
代码可运行
举报
文章被收录于专栏:johnhusterjohnhuster
运行总次数:0
代码可运行

引言

既然 SecurityContext 是存放在 ThreadLocal 中的,而且在每次权限鉴定的时候都是从 ThreadLocal 中获取 SecurityContext 中对应的 Authentication 所拥有的权限,并且不同的 request 是不同的线程,为什么每次都可以从 ThreadLocal 中获取到当前用户对应的 SecurityContext 呢?

入题

在 Web 应用中这是通过 SecurityContextPersistentFilter 实现的,默认情况下其会在每次请求开始的时候从 session 中获取 SecurityContext,然后把它设置给 SecurityContextHolder,在请求结束后又会将 SecurityContextHolder 所持有的 SecurityContext 保存在 session 中,并且清除 SecurityContextHolder 所持有的 SecurityContext。这样当我们第一次访问系统的时候,SecurityContextHolder 所持有的 SecurityContext 肯定是空的,待我们登录成功后,SecurityContextHolder 所持有的 SecurityContext 就不是空的了,且包含有认证成功的 Authentication 对象,待请求结束后我们就会将 SecurityContext 存在 session 中,等到下次请求的时候就可以从 session 中获取到该 SecurityContext 并把它赋予给 SecurityContextHolder 了,由于 SecurityContextHolder 已经持有认证过的 Authentication 对象了,所以下次访问的时候也就不再需要进行登录认证了。

相关代码

代码语言:javascript
代码运行次数:0
运行
复制
           //Stores the supplied security context in the session 
  protected void saveContext(SecurityContext context) {
             final Authentication authentication = context.getAuthentication();
             HttpSession httpSession = request.getSession(false);
 
 
             // See SEC-776
             if (authentication == null || authenticationTrustResolver.isAnonymous(authentication)) {
                 if (logger.isDebugEnabled()) {
                     logger.debug("SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.");
                 }
 
 
                 if (httpSession != null && !contextObject.equals(contextBeforeExecution)) {
                     // SEC-1587 A non-anonymous context may still be in the session
                     // SEC-1735 remove if the contextBeforeExecution was not anonymous
                     httpSession.removeAttribute(springSecurityContextKey);
                 }
                 return;
             }
 
 
             if (httpSession == null) {
                 httpSession = createNewSessionIfAllowed(context);
             }
 
 
             // If HttpSession exists, store current SecurityContext but only if it has
             // actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)
             if (httpSession != null) {
                 // We may have a new session, so check also whether the context attribute is set SEC-1561
                 if (contextChanged(context) || httpSession.getAttribute(springSecurityContextKey) == null) {
  httpSession.setAttribute(springSecurityContextKey, context);
 
 
                     if (logger.isDebugEnabled()) {
                         logger.debug("SecurityContext stored to HttpSession: '" + context + "'");
                     }
                 }
             }
         }
  
 // 
 private SecurityContext readSecurityContextFromSession(HttpSession httpSession) {
         final boolean debug = logger.isDebugEnabled();
 
 
         if (httpSession == null) {
             if (debug) {
                 logger.debug("No HttpSession currently exists");
             }
 
 
             return null;
         }
 
 
         // Session exists, so try to obtain a context from it.
 
 
         Object contextFromSession = httpSession.getAttribute(springSecurityContextKey);
 
 
         if (contextFromSession == null) {
             if (debug) {
                 logger.debug("HttpSession returned null object for SPRING_SECURITY_CONTEXT");
             }
 
 
             return null;
         }
 
 
         // We now have the security context object from the session.
         if (!(contextFromSession instanceof SecurityContext)) {
             if (logger.isWarnEnabled()) {
                 logger.warn(springSecurityContextKey + " did not contain a SecurityContext but contained: '"
                         + contextFromSession + "'; are you improperly modifying the HttpSession directly "
                         + "(you should always use SecurityContextHolder) or using the HttpSession attribute "
                         + "reserved for this class?");
             }
 
 
             return null;
         }
 
 
         if (debug) {
             logger.debug("Obtained a valid SecurityContext from " + springSecurityContextKey + ": '" + contextFromSession + "'");
         }
 
 
         // Everything OK. The only non-null return from this method.
 
 
         return (SecurityContext) contextFromSession;
     }
  

重点看上面颜色标注部分代码!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/08/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 入题
  • 相关代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档