为什么80%的码农都做不了架构师?>>>   

本文就来研究一下spring security的FilterSecurityInterceptor

问题

前面的文章讲了SecurityContextPersistenceFilter是如何将context从session读取并写入的。其中还讲到了AbstractAuthenticationProcessingFilter是如何将鉴权成功的authentication写入context的。那么spring security是如何处理没有authentication的请求呢。答案就在FilterSecurityInterceptor。

filter顺序

spring security内置的各种filter:

Alias Filter Class Namespace Element or Attribute
CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channel
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter session-management/concurrency-control
HEADERS_FILTER HeaderWriterFilter http/headers
CSRF_FILTER CsrfFilter http/csrf
LOGOUT_FILTER LogoutFilter http/logout
X509_FILTER X509AuthenticationFilter http/x509
PRE_AUTH_FILTER AbstractPreAuthenticatedProcessingFilter Subclasses N/A
CAS_FILTER CasAuthenticationFilter N/A
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login
BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http/@servlet-api-provision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http/@jaas-api-provision
REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me
ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous
SESSION_MANAGEMENT_FILTER SessionManagementFilter session-management
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http
SWITCH_USER_FILTER SwitchUserFilter N/A

FilterSecurityInterceptor

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java

/*** Performs security handling of HTTP resources via a filter implementation.* <p>* The <code>SecurityMetadataSource</code> required by this security interceptor is of* type {@link FilterInvocationSecurityMetadataSource}.* <p>* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.* </p>** @author Ben Alex* @author Rob Winch*/
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implementsFilter {
/*** Method that is actually called by the filter chain. Simply delegates to the* {@link #invoke(FilterInvocation)} method.** @param request the servlet request* @param response the servlet response* @param chain the filter chain** @throws IOException if the filter chain fails* @throws ServletException if the filter chain fails*/public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {FilterInvocation fi = new FilterInvocation(request, response, chain);invoke(fi);}
public void invoke(FilterInvocation fi) throws IOException, ServletException {if ((fi.getRequest() != null)&& (fi.getRequest().getAttribute(FILTER_APPLIED) != null)&& observeOncePerRequest) {// filter already applied to this request and user wants us to observe// once-per-request handling, so don't re-do security checkingfi.getChain().doFilter(fi.getRequest(), fi.getResponse());}else {// first time this request being called, so perform security checkingif (fi.getRequest() != null) {fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);}InterceptorStatusToken token = super.beforeInvocation(fi);try {fi.getChain().doFilter(fi.getRequest(), fi.getResponse());}finally {super.finallyInvocation(token);}super.afterInvocation(token, null);}}//......
}

所有的请求到了这一个filter,如果这个filter之前没有执行过的话,那么首先执行的InterceptorStatusToken token = super.beforeInvocation(fi);这个是由AbstractSecurityInterceptor提供。它就是spring security处理鉴权的入口。

AbstractSecurityInterceptor

spring-security-core-4.2.3.RELEASE-sources.jar!/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java

protected InterceptorStatusToken beforeInvocation(Object object) {Assert.notNull(object, "Object was null");final boolean debug = logger.isDebugEnabled();if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {throw new IllegalArgumentException("Security invocation attempted for object "+ object.getClass().getName()+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "+ getSecureObjectClass());}Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object);if (attributes == null || attributes.isEmpty()) {if (rejectPublicInvocations) {throw new IllegalArgumentException("Secure object invocation "+ object+ " was denied as public invocations are not allowed via this interceptor. "+ "This indicates a configuration error because the "+ "rejectPublicInvocations property is set to 'true'");}if (debug) {logger.debug("Public object - authentication not attempted");}publishEvent(new PublicInvocationEvent(object));return null; // no further work post-invocation}if (debug) {logger.debug("Secure object: " + object + "; Attributes: " + attributes);}if (SecurityContextHolder.getContext().getAuthentication() == null) {credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound","An Authentication object was not found in the SecurityContext"),object, attributes);}Authentication authenticated = authenticateIfRequired();// Attempt authorizationtry {this.accessDecisionManager.decide(authenticated, object, attributes);}catch (AccessDeniedException accessDeniedException) {publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated,accessDeniedException));throw accessDeniedException;}if (debug) {logger.debug("Authorization successful");}if (publishAuthorizationSuccess) {publishEvent(new AuthorizedEvent(object, attributes, authenticated));}// Attempt to run as a different userAuthentication runAs = this.runAsManager.buildRunAs(authenticated, object,attributes);if (runAs == null) {if (debug) {logger.debug("RunAsManager did not change Authentication object");}// no further work post-invocationreturn new InterceptorStatusToken(SecurityContextHolder.getContext(), false,attributes, object);}else {if (debug) {logger.debug("Switching to RunAs Authentication: " + runAs);}SecurityContext origCtx = SecurityContextHolder.getContext();SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());SecurityContextHolder.getContext().setAuthentication(runAs);// need to revert to token.Authenticated post-invocationreturn new InterceptorStatusToken(origCtx, true, attributes, object);}}

这里调用了accessDecisionManager来进行判断,如果没有登录态,在到达这个filter之前会先经过AnonymousAuthenticationFilter.java,其Authentication的值为AnonymousAuthenticationToken。如果匿名请求需要登录态的url,或者权限不够,则抛出AccessDeniedException。

小结

spring security两个入口filter分别如下:

  • AbstractAuthenticationProcessingFilter(主要处理登录)
  • FilterSecurityInterceptor(主要处理鉴权)

而SecurityContextPersistenceFilter主要是为这两个filter准备context。

转载于:https://my.oschina.net/go4it/blog/1591160

聊聊FilterSecurityInterceptor相关推荐

  1. 面向对象设计原则_聊聊面向对象的6大设计原则

    程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...

  2. python邮件发送哪个好_最全总结!聊聊 Python 发送邮件的几种方式

    1. 前言 邮件,作为最正式规范的沟通方式,在日常办公过程中经常被用到 我们都知道 Python内置了对 SMTP 的支持,可以发送纯文本.富文本.HTML 等格式的邮件 本文将聊聊利用 Python ...

  3. 今天聊聊分布式锁 No.86

    好了切入正题,一直在工作中会聊到很多锁的问题,今天跟大家一起闲聊一下,究竟什么是锁,为什么需要锁,以及分布式的情况下,怎么设计和实现锁. 什么是锁? 明·魏禧<大铁椎传>上是这样解释的: ...

  4. 聊聊找工作中的项目经验问题(推荐系统和智能问答)

    在求职过程中有这么一句话叫做"金九银十",也就是说,很多时候,求职的黄金时期就是在九月份和十月份,这两个月份中企业需求是最多的,求职的成功率也是最高的.但是随着AI方面的人才越来越 ...

  5. 聊聊Service Mesh:linkerd

    [编者的话]随着企业逐渐将传统的单体应用向微服务或云原生应用的转变,虽然微服务或者云原生应用能给企业带来更多的好处,但也会带来一些具有挑战的问题,如怎么管理从单体应用转向微服务所带来的服务间通讯的复杂 ...

  6. 庖丁解牛迭代器,聊聊那些藏在幕后的秘密

    0x00 前言 \\ 在我之前的一篇博客<细说C#:不是"栈类型"的值类型,从生命周期聊存储位置>的最后,我以总结和后记的方式涉及到一部分迭代器的知识.但是觉得还是不够 ...

  7. 聊聊Unsafe的一些使用技巧

    记得初学 Java 那会,刚学完语法基础,就接触到了反射这个 Java 提供的特性,尽管在现在看来,这是非常基础的知识点,但那时候无疑是兴奋的,瞬间觉得自己脱离了"Java 初学者" ...

  8. 聊聊 TCP 长连接和心跳那些事

    1 前言 可能很多 Java 程序员对 TCP 的理解只有一个三次握手,四次挥手的认识,我觉得这样的原因主要在于 TCP 协议本身稍微有点抽象(相比较于应用层的 HTTP 协议):其次,非框架开发者不 ...

  9. 聊聊算法在面试中的地位

    前段时间,有一位好友找到我,向我打听阿里社招笔试是否看重算法题的考察,我给予了肯定的答复.他表现的有些沮丧,表示自己工程底子很扎实,框架源码也研究地很透彻,唯独算法能力不行,leetcode 上的简单 ...

最新文章

  1. 2020 年度最佳的23个机器学习项目!(附源代码)
  2. 如何给邮件添加背景颜色
  3. ubuntu系统操作常见错误
  4. Win-MASM64汇编语言-MUL/DIV
  5. STC学习:导航按键与数字按键综合控制数码管
  6. Makefile文件生成 GNU Autotools的使用方法
  7. 数据治理之数据质量管理
  8. UGNX1957安装说明视频教程
  9. 数论入门符号_大o符号快速入门
  10. webQQ协议——模拟登录
  11. 接上文安装完opencv后安装viz模块
  12. java web报表开发_2020主流JAVA WEB报表工具对比
  13. galgame序列号怎么查看_国行Switch能完整体验的游戏有哪些?Switch支架掉了怎么办? | Jump指南...
  14. window10 1060 caffe 安装
  15. Go开发 之 容器(数组Array、切片slice、映射map、列表list)
  16. Service START_NOT_STICKY、START_STICKY
  17. 青春无言│用技术定格毕业季最美好的回忆
  18. 上海踩踏事件所想,莫把应急预案当摆设
  19. wampserver 2.4 配置虚拟主机
  20. 戴森“新我发现所”苏州线下体验展启幕 以颠覆性科技传递护发造型新理念

热门文章

  1. 考试君 - 基于.NET 5语言的Furion框架开发在线考试系统
  2. 微信小程序商城,微信小程序微店,长期维护版本
  3. 三、Linux 开机、重启和用户登录注销
  4. 云商城云小店官网源码-修复30套模板支持一键对接各大系统
  5. cnblog div+CSS 布局常识 8问
  6. 项目所需的应用程序未安装,确保已安装项目类型(.csproj)的应用程序的解决办法...
  7. 什么是Viewport Meta(width详解)及在手机上的应用
  8. Magento教程 20:仅限会员留言的产品评论设定!
  9. SVG 教程 (五)文本,Stroke 属性,SVG 滤镜,SVG 模糊效果
  10. 网站统计:第一方Cookie和第三方Cookie