springSecurity学习之springSecurity web如何取得用户信息

web如何取得用户信息

之前说过SecurityContextHolder默认使用的是ThreadLocal来进行存储的,而且每次都会清除,但是web每次请求都会验证用户权限,这是如何做到的呢?

这是通过SecurityContextPersistenceFilter来实现的,每次请求过来都会session中来获取SecurityContext,然后设置到SecurityContextHolder中,请求结束后再清除掉

java 复制代码
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
   HttpServletRequest request = (HttpServletRequest) req;
   HttpServletResponse response = (HttpServletResponse) res;

   if (request.getAttribute(FILTER_APPLIED) != null) {
      // ensure that filter is only applied once per request
      chain.doFilter(request, response);
      return;
   }

   request.setAttribute(FILTER_APPLIED, Boolean.TRUE);


   HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request,
         response);
  // 从session获取SecurityContext
   SecurityContext contextBeforeChainExecution = repo.loadContext(holder);

   try {
     // 将SecurityContext存入SecurityContextHolder
      SecurityContextHolder.setContext(contextBeforeChainExecution);

      chain.doFilter(holder.getRequest(), holder.getResponse());

   }
   finally {
      SecurityContext contextAfterChainExecution = SecurityContextHolder
            .getContext();
      // Crucial removal of SecurityContextHolder contents - do this before anything
      // else.
      SecurityContextHolder.clearContext();
     // 存储SecurityContext
      repo.saveContext(contextAfterChainExecution, holder.getRequest(),
            holder.getResponse());
      request.removeAttribute(FILTER_APPLIED);
   }
}

loadContext获取SecurityContext

使用HttpSessionSecurityContextRepository

java 复制代码
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
   HttpServletRequest request = requestResponseHolder.getRequest();
   HttpServletResponse response = requestResponseHolder.getResponse();
   HttpSession httpSession = request.getSession(false);
		// 从session中获取SecurityContext
   SecurityContext context = readSecurityContextFromSession(httpSession);

   if (context == null) {
      
      context = generateNewContext();

   }

   SaveToSessionResponseWrapper wrappedResponse = new SaveToSessionResponseWrapper(
         response, request, httpSession != null, context);
   requestResponseHolder.setResponse(wrappedResponse);

   return context;
}

从session中获取SecurityContext

java 复制代码
private SecurityContext readSecurityContextFromSession(HttpSession httpSession) {
   final boolean debug = logger.isDebugEnabled();

   if (httpSession == null) {
      return null;
   }

   // Session exists, so try to obtain a context from it.

   Object contextFromSession = httpSession.getAttribute(springSecurityContextKey);

   if (contextFromSession == null) {
      return null;
   }

   // Everything OK. The only non-null return from this method.

   return (SecurityContext) contextFromSession;
}

存储SecurityContext

java 复制代码
public void saveContext(SecurityContext context, HttpServletRequest request,
      HttpServletResponse response) {
   SaveContextOnUpdateOrErrorResponseWrapper responseWrapper = WebUtils
         .getNativeResponse(response,
               SaveContextOnUpdateOrErrorResponseWrapper.class);
   
   if (!responseWrapper.isContextSaved()) {
      responseWrapper.saveContext(context);
   }
}
java 复制代码
protected void saveContext(SecurityContext context) {
   final Authentication authentication = context.getAuthentication();
   HttpSession httpSession = request.getSession(false);

   // See SEC-776
   if (authentication == null || trustResolver.isAnonymous(authentication)) {

      if (httpSession != null && authBeforeExecution != null) {
         // 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) {
        // 存到session中
         httpSession.setAttribute(springSecurityContextKey, context);

         
      }
   }
}

https://zhhll.icu/2024/框架/springSecurity/7.web如何取得用户信息/

相关推荐
程序员黑豆3 小时前
Java包装类:基本类型与对象的桥梁
java·前端·ai编程
mldong7 小时前
"applicant" 契约:退回发起人的闭环设计
java·架构
月华路7 小时前
G1 垃圾回收:脏卡队列、记忆集与并发精化线程机制
java·开发语言
gugucoding8 小时前
47. 【Java】Java内存模型(JMM)与可见性
java·开发语言
zww89491118 小时前
校园跑腿系统开发实战指南:从需求分析到上线部署全流程解析
java
Fluxart.ai9 小时前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
名字还没想好☜9 小时前
Java 线上内存泄漏排查实战:jmap 导堆、MAT 找 GC Roots 与四类常见泄漏
java·开发语言·jvm·内存泄漏
IT爱学堂11 小时前
尚硅谷 - 2025年3月Java+AI大模型应用开发
java·开发语言·人工智能
小贤plus12 小时前
SpringBoot 三大核心注解精讲:@ControllerAdvice、@RestControllerAdvice、@Validated 分组校验(实战)
java
吠品12 小时前
Java byte数组与String互转:编码细节与踩坑记录
java·linux·服务器