- 浏览: 1206135 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
insistboy:
写的太棒了,受不了
WebLogic11g-创建域(Domain) -
goldyeah:
厉害了 困扰我大半个月的问题解决了 谢谢博主
WebLogic11g-单双向SSL配置(以Springside3为例) -
zy315351965:
404伤不起
开源流程引擎Snaker -
nannan408:
双向的时候谷歌提示“不接受您的登录证书,或者您可能没有提供登录 ...
WebLogic11g-单双向SSL配置(以Springside3为例) -
一颗赛艇:
不成功啊。启动有问题 <Security> < ...
WebLogic11g-单双向SSL配置(以Springside3为例)
通过观察Filter的名字,就能大概猜出来这个过滤器的作用,是的,持久化SecurityContext实例。这个过滤器位置是;
org.springframework.security.web.context.SecurityContextPersistenceFilter
废话不说,看源码
通过源码中的注释,应该可以看出来,这个Filter的作用主要是创建一个空的SecurityContext(如果session中没有SecurityContext实例),然后持久化到session中。
接下来看看repo.loadContext(holder);代码:
进一步分析generateNewContext方法
实际上,SecurityContextHolder类也是把创建SecurityContext任务交给具体的SecurityContextHolderStrategy实现类处理,SecurityContextHolder类有一个静态初始化过程
现在来看ThreadLocalSecurityContextHolderStrategy源码
分析到这里,整个过程也清楚了。不过在filter原路返回时,还需要保存这个SecurityContext实例到session中,并且通过SecurityContextHolder将ThreadLocalSecurityContextHolderStrategy中ThreadLocal维持的SecurityContext实例清空。
SaveToSessionResponseWrapper的saveContext方法源码:
org.springframework.security.web.context.SecurityContextPersistenceFilter
废话不说,看源码
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; } final boolean debug = logger.isDebugEnabled(); request.setAttribute(FILTER_APPLIED, Boolean.TRUE); if (forceEagerSessionCreation) { HttpSession session = request.getSession(); if (debug && session.isNew()) { logger.debug("Eagerly created session: " + session.getId()); } } //将request、response对象交给HttpRequestResponseHolder维持 HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response); //通过SecurityContextRepository接口的实现类装载SecurityContext实例 //HttpSessionSecurityContextRepository将产生SecurityContext实例的任务交给SecurityContextHolder.createEmptyContext()完成 //SecurityContextHolder再根据策略模式的不同, //把任务再交给相应策略类完成SecurityContext的创建 //如果没有配置策略名称,则默认为 //ThreadLocalSecurityContextHolderStrategy, //该类直接通过new SecurityContextImpl()创建实例 SecurityContext contextBeforeChainExecution = repo.loadContext(holder); try { //将产生的SecurityContext再通过SecurityContextHolder-> //ThreadLocalSecurityContextHolderStrategy设置到ThreadLocal中 SecurityContextHolder.setContext(contextBeforeChainExecution); //继续把请求流向下一个过滤器执行 chain.doFilter(holder.getRequest(), holder.getResponse()); } finally { //先从SecurityContextHolder获取SecurityContext实例 SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext(); // Crucial removal of SecurityContextHolder contents - do this before anything else. //再把SecurityContext实例从SecurityContextHolder中清空 SecurityContextHolder.clearContext(); //将SecurityContext实例持久化到session中 repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse()); request.removeAttribute(FILTER_APPLIED); if (debug) { logger.debug("SecurityContextHolder now cleared, as request processing completed"); } } }
通过源码中的注释,应该可以看出来,这个Filter的作用主要是创建一个空的SecurityContext(如果session中没有SecurityContext实例),然后持久化到session中。
接下来看看repo.loadContext(holder);代码:
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { HttpServletRequest request = requestResponseHolder.getRequest(); HttpServletResponse response = requestResponseHolder.getResponse(); HttpSession httpSession = request.getSession(false); //从session中获取SecurityContext SecurityContext context = readSecurityContextFromSession(httpSession); //如果获取不到SecurityContext,新建一个空的SecurityContext实例 if (context == null) { if (logger.isDebugEnabled()) { logger.debug("No SecurityContext was available from the HttpSession: " + httpSession +". " + "A new one will be created."); } context = generateNewContext(); } //这里需要注意一下,response装饰器类重新包装了response requestResponseHolder.setResponse(new SaveToSessionResponseWrapper(response, request, httpSession != null, context.hashCode())); return context; }
进一步分析generateNewContext方法
SecurityContext generateNewContext() { SecurityContext context = null; //创建SecurityContext实例并返回 if (securityContextClass == null) { context = SecurityContextHolder.createEmptyContext(); return context; } try { context = securityContextClass.newInstance(); } catch (Exception e) { ReflectionUtils.handleReflectionException(e); } return context; }
实际上,SecurityContextHolder类也是把创建SecurityContext任务交给具体的SecurityContextHolderStrategy实现类处理,SecurityContextHolder类有一个静态初始化过程
static { initialize(); } ………… private static void initialize() { if ((strategyName == null) || "".equals(strategyName)) { // Set default strategyName = MODE_THREADLOCAL; } //默认的SecurityContextHolderStrategy实现类为 //ThreadLocalSecurityContextHolderStrategy if (strategyName.equals(MODE_THREADLOCAL)) { strategy = new ThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) { strategy = new InheritableThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_GLOBAL)) { strategy = new GlobalSecurityContextHolderStrategy(); } else { // Try to load a custom strategy try { Class<?> clazz = Class.forName(strategyName); Constructor<?> customStrategy = clazz.getConstructor(); strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } initializeCount++; }
现在来看ThreadLocalSecurityContextHolderStrategy源码
final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<SecurityContext>(); //~ Methods ======================================================================================================== public void clearContext() { contextHolder.set(null); } public SecurityContext getContext() { SecurityContext ctx = contextHolder.get(); if (ctx == null) { ctx = createEmptyContext(); contextHolder.set(ctx); } return ctx; } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); } //直接new一个SecurityContextImpl对象, //SecurityContextImpl类实现SecurityContext接口 public SecurityContext createEmptyContext() { return new SecurityContextImpl(); } }
分析到这里,整个过程也清楚了。不过在filter原路返回时,还需要保存这个SecurityContext实例到session中,并且通过SecurityContextHolder将ThreadLocalSecurityContextHolderStrategy中ThreadLocal维持的SecurityContext实例清空。
//将SecurityContext实例持久化到session中 repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { //由于之前response装饰器类SaveToSessionResponseWrapper //重新装饰了response SaveContextOnUpdateOrErrorResponseWrapper responseWrapper = (SaveContextOnUpdateOrErrorResponseWrapper)response; // saveContext() might already be called by the response wrapper // if something in the chain called sendError() or sendRedirect(). This ensures we only call it // once per request. if (!responseWrapper.isContextSaved() ) { //SaveToSessionResponseWrapper保存SecurityContext实例 responseWrapper.saveContext(context); } }
SaveToSessionResponseWrapper的saveContext方法源码:
protected void saveContext(SecurityContext context) { // See SEC-776 if (authenticationTrustResolver.isAnonymous(context.getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("SecurityContext contents are anonymous - context will not be stored in HttpSession. "); } return; } HttpSession httpSession = request.getSession(false); if (httpSession == null) { httpSession = createNewSessionIfAllowed(context); } // If HttpSession exists, store current SecurityContextHolder contents but only if // the SecurityContext has actually changed (see JIRA SEC-37) if (httpSession != null && context.hashCode() != contextHashBeforeChainExecution) { //保存SecurityContext到session中 httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, context); if (logger.isDebugEnabled()) { logger.debug("SecurityContext stored to HttpSession: '" + context + "'"); } } }
发表评论
-
Spring Security3源码分析-电子书下载
2012-07-30 14:34 8670提供电子书下载链接。 -
Spring Security3源码分析-CAS支持
2012-05-13 21:03 25926Spring Security3对CAS的支持主要在这个spr ... -
Spring Security3源码分析-SSL支持
2012-05-10 12:48 11209Sping Security3对于SSL的支持仅仅表现在对需要 ... -
Spring Security3源码分析-认证授权分析
2012-05-09 21:59 6554前面分析了FilterChainProxy执行过程,也对常用的 ... -
Spring Security3源码分析-Filter链排序分析
2012-05-09 14:39 15514通过前面Spring Security提供的各种Filter的 ... -
Spring Security3源码分析-RequestCacheAwareFilter分析
2012-05-09 12:55 5075RequestCacheAwareFilter过滤器对应的类路 ... -
Spring Security3源码分析-ExceptionTranslationFilter分析
2012-05-09 10:03 7995ExceptionTranslationFilter过滤器对应 ... -
Spring Security3源码分析-SessionManagementFilter分析-下
2012-05-08 21:03 6468很多spring security3资料在 ... -
Spring Security3源码分析-SessionManagementFilter分析-上
2012-05-08 17:26 11079SessionManagementFilter过滤 ... -
Spring Security3源码分析-AnonymousAuthenticationFilter分析
2012-05-08 10:32 5335AnonymousAuthenticationFilter ... -
Spring Security3源码分析-BasicAuthenticationFilter分析
2012-05-08 09:24 9763BasicAuthenticationFilter过滤器对应的 ... -
Spring Security3源码分析-FilterSecurityInterceptor分析
2012-05-07 17:31 15456FilterSecurityInterceptor过滤器对应的 ... -
Spring Security3源码分析-SecurityContextHolderAwareRequestFilter分析
2012-05-07 10:34 6931SecurityContextHolderAwareReque ... -
Spring Security3源码分析-RememberMeAuthenticationFilter分析
2012-05-06 22:33 6099RememberMeAuthenticationFilter过 ... -
Spring Security3源码分析-UsernamePasswordAuthenticationFilter分析
2012-05-06 11:54 25027UsernamePasswordAuthenticationF ... -
Spring Security3源码分析-LogoutFilter分析
2012-05-06 10:18 10530LogoutFilter过滤器对应的类路径为 org.spri ... -
Spring Security3源码分析-FilterChainProxy执行过程分析
2012-05-06 07:48 4355通过FilterChainProxy的初始化、自定义标签的分析 ... -
Spring Security3源码分析-authentication-manager标签解析
2012-05-05 16:13 21834讲解完http标签的解析过程,authentication-m ... -
Spring Security3源码分析-http标签解析
2012-05-05 15:29 8670在FilterChainProxy初始化的 ... -
Spring Security3源码分析-FilterChainProxy初始化
2012-05-04 16:57 20213很久没有更新博客了,最近对Spring Security做了比 ...
相关推荐
内容概要:本文详细介绍了环形振荡器(Ring VCO)和锁相环(PLL)的设计、仿真与测试方法。针对初学者,提供了从基础电路理论到具体实操步骤的全面指导,涵盖了Cadence软件的使用、PSS/PNOISE仿真、调谐曲线绘制、相位噪声优化以及眼图调试等方面的内容。文中不仅讲解了基本概念和技术要点,还分享了许多实用的操作技巧和常见问题解决方案,如如何正确设置仿真参数、优化相位噪声、处理电源纹波等问题。此外,还附赠了一份详细的ADE_XL用户指南,帮助读者深入理解和掌握相关技术。 适合人群:对模拟IC设计感兴趣的初学者及有一定基础的研发人员。 使用场景及目标:①掌握环形振荡器的基本原理及其在Cadence中的仿真方法;②学会如何进行调谐曲线、相位噪声等关键性能指标的仿真与优化;③提高解决实际工程问题的能力,如电源纹波抑制、眼图调试等。 其他说明:本文特别强调了实践经验的重要性,鼓励读者动手实践并在实践中不断积累经验。同时提醒读者注意一些容易忽视但至关重要的细节,如仿真参数的选择和特殊条件下可能出现的问题。
【java】基于Java+Springboot+Vue的社区医院管理系统(源代码+数据库+万字论文).zip
scratch少儿编程逻辑思维游戏源码-大盗之魂.zip
scratch少儿编程逻辑思维游戏源码-弹跳猫.zip
scratch少儿编程逻辑思维游戏源码-城堡逃脱.zip
内容概要:本文探讨了马里兰电池数据集及其在电池剩余寿命(RUL)预测中的应用,重点介绍了RNN(循环神经网络)和LSTM(长短期记忆网络)这两种深度学习模型的应用。文章首先概述了马里兰电池数据集的特点,它记录了电池在不同环境和使用条件下的关键指标变化,为电池寿命预测提供了宝贵的数据支持。接着,文章详细解释了RNN和LSTM模型的工作原理以及它们在处理序列数据方面的优势,特别是LSTM在处理长时间依赖关系时表现出色。随后,通过一个简单的Python代码示例,展示了如何使用Keras库构建LSTM模型来进行RUL预测,包括数据预处理、模型构建、编译、训练和预测的具体步骤。最后,文章总结了RNN和LSTM模型在电池RUL预测中的重要性和潜力,并展望了未来的研究方向。 适合人群:对电池技术和机器学习感兴趣的科研人员、工程师及学生。 使用场景及目标:适用于希望利用深度学习技术提升电池管理系统的准确性和效率的人群。主要目标是通过学习历史数据,预测电池未来的状态,从而为新电池设计和现有电池维护提供科学依据。 其他说明:文中提供的代码示例仅作为入门指南,实际应用中需要根据具体情况调整模型结构和参数设置,并可能需要高性能计算资源来加速训练过程。
scratch少儿编程逻辑思维游戏源码-道场战场:战斗模拟器.zip
内容概要:本文详细介绍了基于STM32的低压无感BLDC(直流无刷电机)方波方案的全功能版本。该方案采用未封装库的源码,支持脉冲注入用于识别电机转子初始位置,并兼容国产芯片。文中提供了详细的硬件设计(包括原理图、丝印图)、软件实现(特别是脉冲注入和换相逻辑),以及调试方法和技巧。此外,还讨论了霍尔接口的兼容性和自动校准流程,确保系统能够适应不同类型的电机负载。 适合人群:具有一定嵌入式开发经验的研发人员和技术爱好者,尤其是对无感BLDC电机控制系统感兴趣的工程师。 使用场景及目标:①深入理解无感BLDC电机控制的底层逻辑;②掌握脉冲注入和换相逻辑的具体实现;③学习如何优化硬件设计和调试技巧,提高系统的可靠性和性能。 其他说明:该方案不仅适用于学术研究,也可应用于实际产品开发,帮助开发者快速搭建稳定的无感BLDC电机控制系统。
内容概要:本文档是2025年R语言数据分析综合教程,详细介绍了从环境配置到实战案例的完整流程。首先,涵盖环境配置与基础操作,包括安装R语言及RStudio IDE、常用数据分析包的安装与加载、数据导入及基础操作如读取CSV/Excel文件、数据查看与清洗等。接着,深入数据探索与可视化,讲解单变量统计、多变量关系分析,并通过`ggplot2`包进行基础图表和高级图表绘制。然后,进入统计建模与高级分析部分,涉及线性回归模型的构建与评估、主成分分析的数据降维与可视化以及分类资料分析中的卡方检验等内容。最后,通过Palmer企鹅数据集分析和医疗数据分类分析两个实战案例,巩固所学知识。此外,还推荐了中文教程和实战拓展资源,如知乎专栏、CSDN文章、GitHub开源项目和Kaggle数据集等; 适合人群:对R语言数据分析感兴趣的初学者及有一定编程基础的数据分析师; 使用场景及目标:①掌握R语言环境搭建与基础操作技能;②学会利用R语言进行数据探索、可视化及统计建模;③通过实战案例提升解决实际问题的能力; 其他说明:文档内容循序渐进,理论与实践相结合,适合自学或教学使用,读者可根据自身需求选择重点学习内容。
少儿编程scratch项目源代码文件案例素材-日本牛奶广告动画.zip
少儿编程scratch项目源代码文件案例素材-黏糊糊的圣诞节.zip
内容概要:本文详细介绍了基于MATLAB/Simulink平台构建的模块化多电平(MMC)统一潮流控制器(UPFC)仿真模型。首先探讨了MMC子模块的基本结构和电容电压均衡算法,接着讨论了环流抑制方法以及线路侧控制策略。文中还提供了具体的参数配置建议,如子模块数量、电容值、IGBT开关频率等,并展示了仿真的典型效果,包括电压提升和传输功率增加。此外,文章强调了该模型在新能源并网场景中的重要性和实用性。 适合人群:电力系统工程师、科研人员、高校师生等对高压输电线路和潮流控制感兴趣的读者。 使用场景及目标:适用于需要理解和掌握UPFC工作原理及其在MATLAB中的具体实现的研究人员和技术人员。目标是帮助读者搭建能够正常运行的仿真模型,理解UPFC在提高电力系统稳定性和灵活性方面的作用。 其他说明:文中提供的代码片段和参数设置有助于读者快速上手进行相关实验。同时,文章提到的谐波分析和性能评估方法也为进一步优化模型提供了指导。
内容概要:本文详细介绍了如何利用Simulink搭建电力系统稳态仿真模型。首先从同步发电机的选择和参数设置入手,强调了惯性常数H和基底电压的重要性和具体配置方法。接着讨论了负荷模型的选择,推荐使用更贴近实际的ZIP负荷模型而非简单的恒定阻抗模型。然后深入探讨了潮流计算的关键步骤,特别是参考节点的设定及其对后续分析的影响。对于线路建模部分,则提倡采用分布参数线路模块并将其分割为多段以提高仿真的准确性。此外,还提到了一些高级应用,如启用相量仿真模式加速仿真速度以及应对可能出现的暂态不稳定情况的方法。最后鼓励尝试加入风电场元素,进一步研究新能源接入后的系统行为。 适合人群:从事电力系统研究、设计或维护的技术人员,尤其是那些希望深入了解Simulink工具箱在电力工程领域应用的专业人士。 使用场景及目标:适用于需要构建电力系统稳态仿真环境的研究项目或教学课程;旨在帮助用户掌握Simulink平台的基本操作技能,同时培养解决复杂电力网络问题的能力。 其他说明:文中提供了大量MATLAB/Simulink代码片段作为辅助材料,便于读者理解和实践相关概念和技术要点。
scratch少儿编程逻辑思维游戏源码-地牢爬行者.zip
少儿编程scratch项目源代码文件案例素材-南瓜小子.zip
少儿编程scratch项目源代码文件案例素材-日落之旅.zip
scratch少儿编程逻辑思维游戏源码-弹回的球.zip
scratch少儿编程逻辑思维游戏源码-电源竞技场.zip
少儿编程scratch项目源代码文件案例素材-山谷冲撞.zip
scratch少儿编程逻辑思维游戏源码-洞穴冒险 2.zip