一、 熟悉一个模块的最快方法

1. 配置logback文件,打印相应的debug信息

2. 根据相应的信息,打断点查看执行结果

二、spring 使用 DelegatingFilterProxy 管理 filter chain

allow the IoC container to manage the lifecycle instead of the servlet container

org.springframework.web.filter.DelegatingFilterProxy 是 Spring 中定义的一个 Filter 实现类,其作用是代理真正的 Filter 实现类,

也就是说在调用 DelegatingFilterProxy 的 doFilter() 方法时实际上调用的是其代理 Filter 的 doFilter() 方法。使用 DelegatingFilterProxy

的好处就是Filter 类可以使用 Spring 的依赖注入机制方便自由的使用 ApplicationContext 中的 bean。

需要注意的是被代理的 Filter 的初始化方法 init() 和销毁方法 destroy() 默认是不会被执行的。通过设置 DelegatingFilterProxy 的

targetFilterLifecycle 属性为 true,可以使被代理 Filter 与 DelegatingFilterProxy 具有同样的生命周期。

三、 FilterChainProxy

DelegatingFilterProxy 代理的就是一个 FilterChainProxy。一个 FilterChainProxy 中可以包含有多个 FilterChain,但是某个请求

只会对应一个 FilterChain,而一个 FilterChain 中又可以包含有多个 Filter。当我们使用 Spring Security 时,系统会自动为我们

注册一个名为 springSecurityFilterChain,  类型为 FilterChainProxy 的 bean(可查看HttpSecurityBeanDefinitionParser)。

Request Firewalling

An HttpFirewall instance is used to validate incoming requests and create a wrapped request which provides consistent path

values for matching against. See DefaultHttpFirewall, for more information on the type of attacks which the default i

mplementation protects against. A custom implementation can be injected to provide stricter control over the request contents

or if an application needs to support certain types of request which are rejected by default.

Note that this means that you must use the Spring Security filters in combination with a FilterChainProxy if you want this

protection. Don't define them explicitly in your web.xml file.

FilterChainProxy will use the firewall instance to obtain both request and response objects which will be fed down the filter chain,

so it is also possible to use this functionality to control the functionality of the response. When the request has passed through the

security filter chain, the reset method will be called. With the default implementation this means that the original values of

servletPath and pathInfowill be returned thereafter,  instead of the modified ones used for security pattern matching.

四、 AuthenticationManager 和 AuthenticationProvider

AuthenticationManager 是一个用来处理认证请求的接口。在其中只定义了一个方法 authenticate(),该方法只接收一个代表认证请求的

Authentication对象作为参数,如果认证成功,则会返回一个封装了当前用户权限等信息的 Authentication 对象进行返回。

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
boolean debug = logger.isDebugEnabled();

     //使用authenticationProvider列表处理认证请求
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
} if (debug) {
logger.debug("Authentication attempt using " + provider.getClass().getName());
} try {
result = provider.authenticate(authentication);
          //认证成功,跳出循环
if (result != null) {
copyDetails(authentication, result);
break;
}
}
catch (AccountStatusException e) {
prepareException(e, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to
// invalid account status
throw e;
}
catch (InternalAuthenticationServiceException e) {
prepareException(e, authentication);
throw e;
}
catch (AuthenticationException e) {
lastException = e;
}
}
     //没有结果,重试认证
if (result == null && parent != null) {
// Allow the parent to try.
try {
result = parent.authenticate(authentication);
}
catch (ProviderNotFoundException e) {
// ignore as we will throw below if no other exception occurred prior to
// calling parent and the parent
// may throw ProviderNotFound even though a provider in the child already
// handled the request
}
catch (AuthenticationException e) {
lastException = e;
}
}
//认证成功,发布认证结果
if (result != null) {
if (eraseCredentialsAfterAuthentication
&& (result instanceof CredentialsContainer)) {
// Authentication is complete. Remove credentials and other secret data
// from authentication
((CredentialsContainer) result).eraseCredentials();
} eventPublisher.publishAuthenticationSuccess(result);
return result;
} // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) {
lastException = new ProviderNotFoundException(messages.getMessage(
"ProviderManager.providerNotFound",
new Object[] { toTest.getName() },
"No AuthenticationProvider found for {0}"));
} prepareException(lastException, authentication); throw lastException;
}

1.认证过程

在 Spring Security 中,AuthenticationManager 的默认实现是 ProviderManager,而且它不直接自己处理认证请求,而是委托给其所配

置的 AuthenticationProvider 列表,然后会依次使用每一个 AuthenticationProvider 进行认证,如果有一个 AuthenticationProvider 认

证后的结果不为 null,则表示该 AuthenticationProvider 已经认证成功,之后的 AuthenticationProvider 将不再继续认证。然后直接以该

AuthenticationProvider 的认证结果作为 ProviderManager 的认证结果。如果所有的 AuthenticationProvider 的认证结果都为 null,则表

示认证失败,将抛出一个 ProviderNotFoundException。

2. 校验认证

校验认证请求最常用的方法是根据请求的用户名加载对应的 UserDetails,然后比对 UserDetails 的密码与认证请求的密码是否一致。

如DaoAuthenticationProvider其内部使用 UserDetailsService 来负责加载 UserDetails。在认证成功以后会使用加载的

UserDetails 来封装要返回的 Authentication 对象,加载的 UserDetails 对象是包含用户权限等信息的。认证成功返回的 Authentication

对象将会保存在当前的 SecurityContext 中。

4. 在 request 之间共享 SecurityContext

既然 SecurityContext 是存放在 ThreadLocal 中的,而且在每次权限鉴定的时候都是从 ThreadLocal 中获取 SecurityContext 中对应的

Authentication 所拥有的权限,但不同的 request 是不同的线程,为什么每次都可以从 ThreadLocal 中获取到当前用户对应的 SecurityContext 呢?

每次请求开始的时候从 session 中获取 SecurityContext,然后把它设置给 SecurityContextHolder

参考:

极客学院:初识Spring Security

Spring Security 4.2.3 API

最新文章

  1. 解决css3毛玻璃效果(blur)有白边问题
  2. web前端书籍
  3. 基于HTML5的3D网络拓扑树呈现
  4. [转载]Eclipse提示No java virtual machine
  5. TableInputFormat分片及分片数据读取源码级分析
  6. 多校5 1001 HDU5781 ATM Mechine 记忆化搜索+概率
  7. C# 学习之旅(2)--- 意外的收获
  8. 关于DataTables一些小结
  9. python打包成exe(py2exe)
  10. org.apache.hadoop.security.AccessControlException: Permission denied: user=?, access=WRITE, inode=&quot;/&quot;:hadoop:supergroup:drwxr-xr-x 异常解决
  11. MongoDB备份恢复与导出导入
  12. shiro的sessionManager类继承结构及主要类方法
  13. tagName与nodeName的区别
  14. 如何只在IE上加载CSS样式表
  15. SQL 四大功能DDL/DML/DCL/TCL
  16. 家庭记账本之微信小程序(三)
  17. 全国绿色计算大赛 模拟赛第一阶段(C++)第1关:求和
  18. Java中float和double转换的问题
  19. JZOJ.5326【NOIP2017模拟8.21】LCA 的统计
  20. ibator自动代码生成

热门文章

  1. 《深入理解Java虚拟机》读书笔记:垃圾收集器与内存分配策略
  2. rqalpha探究 2 接入mod
  3. Springboot学习笔记(三)-常用注入组件方式
  4. [转]搞个这样的 APP 要多久
  5. 两台centos之间传送文件
  6. [Hinton] Neural Networks for Machine Learning - Basic
  7. [Android] 基于 Linux 命令行构建 Android 应用(七):自动化构建
  8. [Python] pip 简明指南
  9. 二分求幂/快速幂取模运算——root(N,k)
  10. Failed to resolve: com.android.support:appcompat-v7:27.0.1问题解决