Spring Security认证授权流程

一. Spring Security认证授权流程图概述

在上一章节中,威哥就给各位贴出过Spring Security的认证授权流程图,该图展示了认证授权时经历的核心API,并且展示了认证授权流程。接下来我们结合源码,一点点分析认证和授权的实现过程。

二. 简要剖析认证授权实现流程的代码逻辑

Spring Security的认证授权流程其实是非常复杂的,在我们对源码还不够了解的情况下,威哥先给各位简要概括一下这个认证和授权流程,大致如下:

  1. 用户登录前,默认生成的Authentication对象处于未认证状态,登录时会交由Authentication Manager负责进行认证。
  2. AuthenticationManager会将Authentication中的用户名/密码与UserDetails中的用户名/密码对比,完成认证工作,认证成功后会生成一个已认证状态的Authentication对象;
  3. 最后把认证通过的Authentication对象写入到SecurityContext中,在用户有后续请求时,可从Authentication中检查权限。

我们可以借鉴一下Spring Security官方文档中提供的一个最简化的认证授权流程代码,来认识一下认证授权的实现过程,该代码省略了UserDetails操作,只做了简单认证,可以对认证授权有个大概了解。

解释

public class AuthenticationExample { private static AuthenticationManager am = new SampleAuthenticationManager(); public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (true) { //模拟输入用户名密码 System.out.println("Please enter your username:"); String name = in.readLine(); System.out.println("Please enter your password:"); String password = in.readLine(); try { //根据用户名/密码,生成未认证Authentication Authentication request = new UsernamePasswordAuthenticationToken(name, password); //交给AuthenticationManager 认证 Authentication result = am.authenticate(request); //将已认证的Authentication放入SecurityContext SecurityContextHolder.getContext().setAuthentication(result); break; } catch (AuthenticationException e) { System.out.println("Authentication failed: " + e.getMessage()); } } System.out.println("Successfully authenticated. Security context contains: " + SecurityContextHolder.getContext().getAuthentication()); } } //认证类 class SampleAuthenticationManager implements AuthenticationManager { //配置一个简单的用户权限集合 static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>(); static { AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER")); } public Authentication authenticate(Authentication auth) throws AuthenticationException { //如果用户名和密码一致,则登录成功,这里只做了简单认证 if (auth.getName().equals(auth.getCredentials())) { //认证成功,生成已认证Authentication,比未认证多了权限 return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES); } throw new BadCredentialsException("Bad Credentials"); } }

以上代码只是简单的模拟了认证的过程,那么真正的认证授权操作,是不是也这样呢?接下来请跟着威哥,咱们结合源码进行详细的剖析。

三. Spring Security认证流程源码详解

1. Spring Security过滤器链执行顺序

在 Spring Security 中,与认证、授权相关的校验其实都是利用一系列的过滤器来完成的,这些过滤器共同组成了一个过滤器链,如下图所示:

你可能会问,我们怎么知道这些过滤器在执行?其实我们只要开启Spring Security的debug调试模式,开发时就可以在控制台看到这些过滤器的执行顺序,如下:

所以在上图中可以看到,Spring Security中默认执行的过滤器顺序如下:

  • WebAsyncManagerIntegrationFilter
  • SecurityContextPersistenceFilter
  • HeaderWriterFilter
  • CsrfFilter
  • LogoutFilter
  • UsernamePasswordAuthenticationFilter
  • DefaultLoginPageGeneratingFilter
  • DefaultLogoutPageGeneratingFilter
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • AnonymousAuthenticationFilter:如果之前的认证机制都没有更新 Security Context Holder 拥有的 Authentication,那么一个 Anonymous Authen tication Token 将会设给 Security Context Holder。
  • SessionManagementFilter
  • ExceptionTranslationFilter:用于处理在 Filter Chain 范围内抛出的 Access Denied Exception 和 Authentication Exception,并把它们转换为对应的 Http 错误码返回或者跳转到对应的页面。
  • FilterSecurityInterceptor:负责保护 Web URI,并且在访问被拒绝时抛出异常。

2. SecurityContextPersistenceFilter

在上面的过滤器链中,我们可以看到 Security Context PersistenceFilter这个过滤器。Security Context Persistence Filter是Security中的一个拦截器,它的执行时机非常早,当请求来临时它会从Security Context Repository中把SecurityContext对象取出来,然后放入Security Context Holder的Thread Local中。在所有拦截器都处理完成后,再把Security Context存入Security Context Repository,并清除Security Context Holder 内的 Security Context 引用。

3. AbstractAuthenticationProcessingFilter

在上面图中所展示的一系列的过滤器中,和认证授权直接相关的过滤器是 Abstract Authentication Processing Filter 和 Username Password Authentication Filter。但是你可能又会问,怎么没看到 Abstract Authentication Processing Filter 这个过滤器呢?这是因为它是一个抽象的父类,其内部定义了认证处理的过程,Username Password Authentication Filter 就继承自 Abstract Authentication Processing Filter。如下图所示:

从上图中我们可以看出,Abstract Authentication ProcessingFilter的父类是Generic Filter Bean,而 GenericFilterBean 是 Spring 框架中的过滤器类,最终的父接口是Filter,也就是我们熟悉的过滤器。那么既然是Filter的子类,肯定会执行其中最核心的do Filter()方法,我们来看看Abstract Authentication Processing Filter的do Filter()方法源码。

从上面的源码中我们可以看出,doFilter()方法的内部实现并不复杂,里面就只引用了5个方法,如下:

解释

requiresAuthentication(request, response); authResult = attemptAuthentication(request, response); sessionStrategy.onAuthentication(authResult, request, response); unsuccessfulAuthentication(request, response, failed); successfulAuthentication(request, response, chain, authResult);

这几个方法具体的作用如下:

  1. 首先执行 requiresAuthentication(HttpServletRequest, Http Servlet Response) 方法,来决定是否需要进行验证操作;
  2. 如果需要验证,接着就会调用 attempt Authentication(Http Servlet Request, Http Servlet Response) 方法来封装用户信息再进行验证,可能会有三种结果产生:
  3. 如果返回的Authentication对象为Null,则表示身份验证不完整,该方法将立即结束返回。
  4. 如果返回的Authentication对象不为空,则调用配置的 SessionAuthenticationStrategy 对象,执行onAuthentication()方法,然后调用 successfulAuthentication(HttpServletRequest,HttpServletResponse,FilterChain,Authentication) 方法。
  5. 验证时如果发生 AuthenticationException,则执行unsuccessful Authentication (HttpServletRequest, HttpServletResponse, Authentication Exception) 方法。

我们在上面的源码中得知有个attempt Authentication()方法,该方法是一个抽象方法,由子类来具体实现。

这个抽象方法由子类Username Password Authentication Filter来实现,如下图。

Abstract Authentication Processing Filter是一个比较复杂的类,内部的处理流程比较多,我们做个简单梳理,如下图所示:

综上所述,我们可知AbstractAuthenticationProcessingFilter类,可以负责处理所有的HTTP Request和Response对象,并将其封装成AuthenticationMananger可以处理的Authentication对象。在身份验证成功或失败之后,将对应的行为转换为HTTP的Response对象。同时还能处理一些Web特有的资源,比如Session和Cookie等操作。到此为止,我们已经把Abstract Authentication Processing Filter这个类的核心功能给了解清楚了,接下来我们学习Abstract Authentication Processing Filter的子类Username Password Authentication Filter。

4. UsernamePasswordAuthenticationFilter

我在上一小节中说过,在 Spring Security 中,认证与授权的相关校验是在Abstract Authentication Processing Filter这个过滤器中完成的,但是该类是一个抽象类,它有个子类Username Password Authentication Filter,该类是和认证直接相关的过滤器实现子类。我们来看一下该类的核心源码:

解释

public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password"; ... ... // ~ Constructors // =================================================================================================== public UsernamePasswordAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); } public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } @Nullable protected String obtainPassword(HttpServletRequest request) { return request.getParameter(passwordParameter); } @Nullable protected String obtainUsername(HttpServletRequest request) { return request.getParameter(usernameParameter); } protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } ......其他略...... }

我来解释一下上面的源码:

  1. 首先我们从构造方法中可以得知,该过滤器 只对post请求方式的"/login"接口有效;
  2. 然后在该过滤器中,再利用 obtainUsername 和 obtainPassword 方法,提取出请求里边的用户名/密码,提取方式就是 request.getParameter,这也是为什么 Spring Security 中默认的表单登录要通过 key/value 的形式传递参数,而不能传递 JSON 参数。如果像传递 JSON 参数,我们可以通过修改这里的代码来进行实现。
  3. 获取到请求里传递来的用户名/密码之后,接下来会 构造一个 Username Password AuthenticationToken 对象,传入 username 和 password。其中 username 对应了 UsernamePasswordAuthenticationToken 中的 principal 属性,而 password 则对应了它的 credentials 属性。
  4. 接下来 再利用 setDetails 方法给 details 属性赋值,UsernamePasswordAuthenticationToken 本身是没有 details 属性的,这个属性是在它的父类 AbstractAuthenticationToken 中定义的。details 是一个对象,这个对象里边存放的是 Web Authentication Details 实例,该实例主要描述了 请求的 remote Address 以及请求的 sessionId 这两个信息。
  5. 最后一步,就是利用AuthenticationManager对象来调用 authenticate() 方法去做认证校验。

5. AuthenticationManager与ProviderManager

咱们在上面 Username Password Authentication Token 类的 attempt Authentication() 方法中得知,该方法的最后一步会进行关于认证的校验,而要进行认证操作首先要获取到一个 Authentication Manager 对象,这里默认拿到的是Authentication Manager的子类Provider Manager ,如下图所示:

所以接下来我们要进入到 ProviderManager 的 authenticate()方法中,来看看认证到底是怎么实现的。因为这个方法的实现代码比较长,我这里仅摘列出几个重要的地方:

ProviderManager类中的authenticate()方法代码很长,我通过截图,把该方法中的重点地方做了红色标记,方便大家重点记忆。

其实Spring Security中关于认证的重要逻辑几乎都是在这里完成的,所以接下来我分步骤,一点点带大家分析该认证的实现流程。

首先利用反射,获取到要认证的 authentication 对象的 Class字节码,如下图:

判断当前 provider 是否支持该 authentication 对象,如下图:

如果当前provider不支持该 authentication 对象,则退出当前判断,进行下一次判断。

如果支持,则调用 provider 的 authenticate 方法开始做校验,校验完成后,会返回一个新的 Authentication,如下图:

这里的 provider 会有多个,我们在上一章节给大家介绍过,如下图:

这里如果 provider 的 authenticate 方法没能返回一个 Authentication 认证对象,则会调用 provider 的 parent 对象中的 authenticate 方法继续校验。

而如果通过了校验,返回了一个Authentication 认证对象,则调用 copyDetails()方法把旧 Token 的 details 属性拷贝到新的 Token 中,如下图。

接下来会调用 eraseCredentials()方法来擦除凭证信息,也就是我们的密码,这个擦除方法比较简单,就是将 Token 中的 credentials 属性置空。

最后通过 publishAuthenticationSuccess() 方法将认证成功的事件广播出去。

在以上代码的for循环中,第一次拿到的 provider 是一个 Anonymous Authentication Provider。这个provider 是不支持 Username Password Authentication Token的,所以会直接在 provider.supports()方法中返回 false,结束当前for循环,并进入到下一个 if 判断中,最后直接调用 parent 的 authenticate 方法进行校验。

而parent就是 ProviderManager对象,所以会再次回到这个authenticate()方法中。当再次回到authenticate() 方法时,provider会变成第二个Provider,即Dao Authentication Provider,这个 provider 是支持 UsernamePasswordAuthenticationToken 的,所以会顺利进入到该类的authenticate()方法去执行。

6. DaoAuthenticationProvider

DaoAuthenticationProvider继承自Abstract UserDetails Authentication Provider,DaoAuthenticationProvider类结构如下所示:

DaoAuthenticationProvider类中并没有重写 authenticate() 方法,authenticate() 方法是在父类AbstractUserDetailsAuthenticationProvider中实现的。所以我们看看Abstract User Details Authentication Provider # authenticate()方法的源码,这里我对该源码做了一些简化:

解释

public Authentication authenticate(Authentication authentication) throws AuthenticationException { ...... //获取authentication中存储的用户名 String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); //判断是否使用了缓存 boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { cacheWasUsed = false; try { //retrieveUser()是一个抽象方法,由子类DaoAuthenticationProvider来实现,用于根据用户名查询用户。 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { ...... } try { //进行必要的认证前和额外认证的检查 preAuthenticationChecks.check(user); //这是抽象方法,由子类DaoAuthenticationProvider来实现,用于进行密码对比 additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { //在发生异常时,尝试着从缓存中进行对象的加载 cacheWasUsed = false; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } } //认证后的检查操作 postAuthenticationChecks.check(user); if (!cacheWasUsed) { this.userCache.putUserInCache(user); } Object principalToReturn = user; if (forcePrincipalAsString) { principalToReturn = user.getUsername(); } //认证成功后,封装认证对象 return createSuccessAuthentication(principalToReturn, authentication, user); }

结合上面的源码,我们再做进一步的分析梳理:

我在上面说过,DaoAuthenticationProvider这个子类并没有重写authenticate()方法,而是在父类AbstractUserDetailsAuthenticationProvider中实现的。Abstract User Details Authentication Provider 类中的 authenticate()方法执行时,首先会从 Authentication 提取出登录用户名,如下图所示:

然后利用得到的 username,先去缓存中查询是否有该用户,如下所示:

如果缓存中没有该用户,则去执行 retrieveUser() 方法获取当前用户对象。而这个retrieveUser()方法是个抽象方法,在Abstract User Details Authentication Provider类中并没有实现,是由子类DaoAuthenticationProvider来实现的。

在DaoAuthenticationProvider类的retrieveUser() 方法中,会调用get User Details Service()方法,得到UserDetailsService对象,执行我们自己在登录时候编写的 loadUserByUsername()方法,然后返回一个UserDetails对象,也就是我们的登录对象。如下图所示。

接下来会继续往下执行preAuthenticationChecks.check()方法,检验 user 中各账户属性是否正常,例如账户是否被禁用、是否被锁定、是否过期等,如下所示。

接着会继续往下执行additionalAuthenticationChecks()方法,进行密码比对。而该方法也是抽象方法,也是由子类DaoAuthenticationProvider进行实现。我们在注册用户时对密码加密之后,Spring Security就是在这里进行密码比对的。如下所示。

然后在 postAuthenticationChecks.check()方法中检查密码是否过期,如下所示。

然后判断是否进行了缓存,如果未进行缓存,则执行缓存操作,这个缓存是由 SpringCacheBasedUserCache类来实现的。

我们这里如果没有对缓存做配置,则会执行默认的缓存配置操作。如果我们对缓存进行了自定义的配置,比如配置了RedisCache,就可以把对象缓存到redis中。

接下来有一个 forcePrincipalAsString 属性,该属性表示 是否强制将 Authentication 中的 principal 属性设置为字符串,这个属性其实我们一开始就在 UsernamePasswordAuthenticationFilter 类中定义为了字符串(即username)。但是默认情况下,当用户登录成功之后,这个属性的值就变成当前用户这个对象了。之所以会这样,就是因为 forcePrincipalAsString 默认为 false,不过这块其实不用改,就用 false,这样在后期获取当前用户信息的时候反而方便很多。

最后通过createSuccessAuthentication()方法构建出一个新的 Username Password Authentication Token对象。

这样我们最终得到了认证通过的Authentication对象,并把该对象利用publish Authentication Success()方法,将该事件发布出去。

Spring Security会监听这个事件,接收到这个Authentication对象,进而调用 SecurityContextHolder.getContext().setAuthentication(...)方法,将 Authentication Manager返回的 Authentication对象,存储在当前的 Security Context 对象中。

7. 保存Authentication认证信息

我们在上面说,Authentication认证信息最终是保存在SecurityContext 对象中的,但是具体的代码是在哪里实现的呢?

我们来到 UsernamePasswordAuthenticationFilter 的父类 Abstract Authentication ProcessingFilter 中,这个类我们经常会见到,因为很多时候当我们想要在 Spring Security 自定义一个登录验证码或者将登录参数改为 JSON 的时候,我们都需自定义过滤器继承自 AbstractAuthenticationProcessingFilter。

解释

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; if (!requiresAuthentication(request, response)) { chain.doFilter(request, response); return; } ...... Authentication authResult; try { authResult = attemptAuthentication(request, response); if (authResult == null) { // return immediately as subclass has indicated that it hasn't completed // authentication return; } sessionStrategy.onAuthentication(authResult, request, response); } catch (InternalAuthenticationServiceException failed) { logger.error( "An internal error occurred while trying to authenticate the user.", failed); unsuccessfulAuthentication(request, response, failed); return; } catch (AuthenticationException failed) { // Authentication failed unsuccessfulAuthentication(request, response, failed); return; } // Authentication success if (continueChainBeforeSuccessfulAuthentication) { chain.doFilter(request, response); } //处理认证后的操作 successfulAuthentication(request, response, chain, authResult); }

在上面的源码中,有个successfulAuthentication()方法,如下图。

当UsernamePasswordAuthenticationFilter#attemptAuthentication()方法被触发执行时,如果登录时抛出异常,unsuccessfulAuthentication()方法会被调用;而当登录成功时,successfulAuthentication()方法则会被调用,正是这个方法来保存的Authentication认证信息,我们来看看这个源码。

在这里有一段很重要的代码,就是 SecurityContextHolder.getContext().setAuthentication(authResult),登录成功的用户信息就被保存在这里。在认证成功后,我们就可以在任何地方,通过 Security ContextHolder.getContext()获取到Authentication认证信息。

最后大家还看到还有一个 successHandler.onAuthenticationSuccess()方法,这是我们在 SecurityConfig中配置的登录成功时的回调处理方法,就是在这里被触发。

8. ExceptionTranslationFilter

Spring Security在进行认证授权的过程中,可能会产生各种认证授权异常。对于这些异常,都是由ExceptionTranslationFilter来捕获过滤器链中产生的所有异常并进行处理的。但是它只会处理两类异常:AuthenticationException 和 Access Denied Exception,其它的异常它会继续抛出。

如果捕获到的是 AuthenticationException异常,那么将会使用其对应的 Authentication EntryPoint 里的commence()方法来处理。在处理之前,Exception Translation Filter先使用 RequestCache 将当前的Http Serverlet Request的信息保存起来,以至于用户认证登录成功后可以跳转到之前指定跳转到的界面。

如果捕获到的是 AccessDeniedException异常,那么将根据当前用户是否已经登录认证做出不同的处理。如果未登录,则会使用关联的 AuthenticationEntryPoint 的 commence()方法来进行处理;否则将会使用关联的 AccessDeniedHandler 的handle()方法来进行处理。

9. FilterSecurityInterceptor

当我们经历了前面一系列的认证授权处理后,最后还有一个FilterSecurityInterceptor 用于保护Http资源,它内部引用了一个AccessDecisionManager和一个Authentication Manager对象。它会从 SecurityContextHolder 获取 Authentication对象,然后通过 SecurityMetadataSource 可以得知当前是否在请求受保护的资源。如果请求的是那些受保护的资源,如果Authentication.isAuthenticated() 返回false或者FilterSecurityInterceptor的alwaysReauthenticate 属性为 true,那么将会使用其引用的 AuthenticationManager 再认证一次。认证之后再使用认证后的 Authentication 替换 SecurityContextHolder 中拥有的旧的那个Authentication对象,然后就是利用 AccessDecisionManager 进行权限的检查。

注:

  • AuthenticationEntryPoint 是在用户未登录时,用于引导用户进行登录认证的;
  • AccessDeniedHandler 是在用户已经登录后,但是访问了自身没有权限的资源时做出的对应处理。

10. 认证流程总结

Spring Security进行认证授权的源码执行流程,大致就是上面我婆媳剖析的那么,接下来我对认证过程做个简单总结:

  • 首先用户在登录表单中,填写用户名和密码,进行登录操作;
  • AbstractAuthenticationProcessingFilter结合UsernamePasswordAuthenticationToken过滤器,将获取到的用户名和密码封装成一个实现了 Authentication 接口的实现子类 UsernamePasswordAuthenticationToken对象。
  • 将上述产生的 token 对象传递给 AuthenticationManager的具体子类ProviderManager 进行登录认证。
  • ProviderManager 认证成功后将会返回一个封装了用户权限等信息的 Authentication 对象。
  • 通过调用 SecurityContextHolder.getContext().setAuthentication(...) 将 AuthenticationManager 返回的 Authentication 对象赋予给当前的 Security Context。

我们可以结合下面两图,和上面的源码,深入理解掌握Spring Security的认证授权流程。

以后出去面试时,给面试官讲解这个简化流程就差不多了。

四. 相关面试题

另外可能我们有这么一个疑问:如何在 request 之间共享 SecurityContext?

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

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

到此为止,我就给大家剖析了Spring Security中最核心的认证授权源码,也就是底层执行原理。如果你可以把这些源码理解掌握了,出去面试时,就靠这一个知识点,就足以征服面试官,让面试官臣服在你的“牛逼”之下。你学会了吗?评论区留言666呗!

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
序言 I. 入门 1. 介绍 1.1. Spring Security是什么? 1.2. 历史 1.3. 发行版本号 1.4. 获得Spring Security 1.4.1. 项目模块 1.4.1.1. Core - spring-security-core.jar 1.4.1.2. Web - spring-security-web.jar 1.4.1.3. Config - spring-security-config.jar 1.4.1.4. LDAP - spring-security-ldap.jar 1.4.1.5. ACL - spring-security-acl.jar 1.4.1.6. CAS - spring-security-cas-client.jar 1.4.1.7. OpenID - spring-security-openid.jar 1.4.2. 获得源代码 2. Security命名空间配置 2.1. 介绍 2.1.1. 命名空间的设计 2.2. 开始使用安全命名空间配置 2.2.1. 配置web.xml 2.2.2. 最小 <http>配置 2.2.2.1. auto-config包含了什么? 2.2.2.2. 表单和基本登录选项 2.2.3. 使用其他认证提供器 2.2.3.1. 添加一个密码编码器 2.3. 高级web特性 2.3.1. Remember-Me认证 2.3.2. 添加HTTP/HTTPS信道安全 2.3.3. 会话管理 2.3.3.1. 检测超时 2.3.3.2. 同步会话控制 2.3.3.3. 防止Session固定攻击 2.3.4. 对OpenID的支持 2.3.4.1. 属性交换 2.3.5. 添加你自己的filter 2.3.5.1. 设置自定义 AuthenticationEntryPoint 2.4. 保护方法 2.4.1. <global-method-security>元素 2.4.1.1. 使用protect-pointcut添加安全切点 2.5. 默认的AccessDecisionManager 2.5.1. 自定义AccessDecisionManager 2.6. 验证管理器和命名空间 3. 示例程序 3.1. Tutorial示例 3.2. Contacts 3.3. LDAP例子 3.4. CAS例子 3.5. Pre-Authentication例子 4. Spring Security社区 4.1. 任务跟踪 4.2. 成为参与者 4.3. 更多信息 II. 结构和实现 5. 技术概述 5.1. 运行环境 5.2. 核心组件 5.2.1. SecurityContextHolder, SecurityContext 和 Authentication对象 5.2.1.1. 获得当前用户的信息 5.2.2. UserDetailsService 5.2.3. GrantedAuthority 5.2.4. 小结 5.3. 验证 5.3.1. 什么是Spring Security的验证呢? 5.3.2. 直接设置SecurityContextHolder的内容 5.4. 在web应用中验证 5.4.1. ExceptionTranslationFilter 5.4.2. AuthenticationEntryPoint 5.4.3. 验证机制 5.4.4. 在请求之间保存SecurityContext。 5.5. Spring Security中的访问控制(验证) 5.5.1. 安全和AOP建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager 5.5.2.4. 扩展安全对象模型 5.6. 国际化 6. 核心服务 6.1. The AuthenticationManager, ProviderManager 和 AuthenticationProviders 6.1.1. DaoAuthenticationProvider 6.2. UserDetailsService实现 6.2.1. 内存认证 6.2.2. JdbcDaoImpl 6.2.2.1. 权限分组 6.3. 密码加密 6.3.1. 什么是散列加密? 6.3.2. 为散列加点儿盐 6.3.3. 散列和认证 III. web应用安全 7. 安全过滤器链 7.1. DelegatingFilterProxy 7.2. FilterChainProxy 7.2.1. 绕过过滤器链 7.3. 过滤器顺序 7.4. 使用其他过滤器 —— 基于框架 8. 核心安全过滤器 8.1. FilterSecurityInterceptor 8.2. ExceptionTranslationFilter 8.2.1. AuthenticationEntryPoint 8.2.2. AccessDeniedHandler 8.3. SecurityContextPersistenceFilter 8.3.1. SecurityContextRepository 8.4. UsernamePasswordAuthenticationFilter 8.4.1. 认证成功和失败的应用流程 9. Basic(基本)和Digest(摘要)验证 9.1. BasicAuthenticationFilter 9.1.1. 配置 9.2. DigestAuthenticationFilter 9.2.1. Configuration 10. Remember-Me认证 10.1. 概述 10.2. 简单基于散列标记的方法 10.3. 持久化标记方法 10.4. Remember-Me接口和实现 10.4.1. TokenBasedRememberMeServices 10.4.2. PersistentTokenBasedRememberMeServices 11. 会话管理 11.1. SessionManagementFilter 11.2. SessionAuthenticationStrategy 11.3. 同步会话 12. 匿名认证 12.1. 概述 12.2. 配置 12.3. AuthenticationTrustResolver IV. 授权 13. 验证架构 13.1. 验证 13.2. 处理预调用 13.2.1. AccessDecisionManager 13.2.2. 基于投票的AccessDecisionManager实现 13.2.2.1. RoleVoter 13.2.2.2. AuthenticatedVoter 13.2.2.3. Custom Voters 13.3. 处理后决定 14. 安全对象实现 14.1. AOP联盟 (MethodInvocation) 安全拦截器 14.1.1. 精确的 MethodSecurityIterceptor 配置 14.2. AspectJ (JoinPoint) 安全拦截器 15. 基于表达式的权限控制 15.1. 概述 15.1.1. 常用内建表达式 15.2. Web 安全表达式 15.3. 方法安全表达式 15.3.1. @Pre 和 @Post 注解 15.3.1.1. 访问控制使用 @PreAuthorize 和 @PostAuthorize 15.3.1.2. 过滤使用 @PreFilter 和 @PostFilter V. 高级话题 16. 领域对象安全(ACLs) 16.1. 概述 16.2. 关键概念 16.3. 开始 17. 预认证场景 17.1. 预认证框架类 17.1.1. AbstractPreAuthenticatedProcessingFilter 17.1.2. AbstractPreAuthenticatedAuthenticationDetailsSource 17.1.2.1. J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 17.1.3. PreAuthenticatedAuthenticationProvider 17.1.4. Http403ForbiddenEntryPoint 17.2. 具体实现 17.2.1. 请求头认证(Siteminder) 17.2.1.1. Siteminder示例配置 17.2.2. J2EE容器认证 18. LDAP认证 18.1. 综述 18.2. 在Spring Security里使用LDAP 18.3. 配置LDAP服务器 18.3.1. 使用嵌入测试服务器 18.3.2. 使用绑定认证 18.3.3. 读取授权 18.4. 实现类 18.4.1. LdapAuthenticator实现 18.4.1.1. 常用功能 18.4.1.2. BindAuthenticator 18.4.1.3. PasswordComparisonAuthenticator 18.4.1.4. 活动目录认证 18.4.2. 链接到LDAP服务器 18.4.3. LDAP搜索对象 18.4.3.1. FilterBasedLdapUserSearch 18.4.4. LdapAuthoritiesPopulator 18.4.5. Spring Bean配置 18.4.6. LDAP属性和自定义UserDetails 19. JSP标签库 19.1. 声明Taglib 19.2. authorize标签 19.3. authentication 标签 19.4. accesscontrollist 标签 20. Java认证授权服务(JAAS)供应器 20.1. 概述 20.2. 配置 20.2.1. JAAS CallbackHandler 20.2.2. JAAS AuthorityGranter 21. CAS认证 21.1. 概述 21.2. CAS是如何工作的 21.3. 配置CAS客户端 22. X.509认证 22.1. 概述 22.2. 把X.509认证添加到你的web系统中 22.3. 为tomcat配置SSL 23. 替换验证身份 23.1. 概述 23.2. 配置 A. 安全数据库表结构 A.1. User表 A.1.1. 组权限 A.2. 持久登陆(Remember-Me)表 A.3. ACL表 A.3.1. Hypersonic SQL A.3.1.1. PostgreSQL B. 安全命名空间 B.1. Web应用安全 - <http>元素 B.1.1. <http>属性 B.1.1.1. servlet-api-provision B.1.1.2. path-type B.1.1.3. lowercase-comparisons B.1.1.4. realm B.1.1.5. entry-point-ref B.1.1.6. access-decision-manager-ref B.1.1.7. access-denied-page B.1.1.8. once-per-request B.1.1.9. create-session B.1.2. <access-denied-handler> B.1.3. <intercept-url>元素 B.1.3.1. pattern B.1.3.2. method B.1.3.3. access B.1.3.4. requires-channel B.1.3.5. filters B.1.4. <port-mappings>元素 B.1.5. <form-login>元素 B.1.5.1. login-page B.1.5.2. login-processing-url B.1.5.3. default-target-url B.1.5.4. always-use-default-target B.1.5.5. authentication-failure-url B.1.5.6. authentication-success-handler-ref B.1.5.7. authentication-failure-handler-ref B.1.6. <http-basic>元素 B.1.7. <remember-me>元素 B.1.7.1. data-source-ref B.1.7.2. token-repository-ref B.1.7.3. services-ref B.1.7.4. token-repository-ref B.1.7.5. key属性 B.1.7.6. token-validity-seconds B.1.7.7. user-service-ref B.1.8. <session-management> 元素 B.1.8.1. session-fixation-protection B.1.9. <concurrent-control>元素 B.1.9.1. max-sessions属性 B.1.9.2. expired-url属性 B.1.9.3. error-if-maximum-exceeded属性 B.1.9.4. session-registry-alias和session-registry-ref属性 B.1.10. <anonymous>元素 B.1.11. <x509>元素 B.1.11.1. subject-principal-regex属性 B.1.11.2. user-service-ref属性 B.1.12. <openid-login>元素 B.1.13. <logout>元素 B.1.13.1. logout-url属性 B.1.13.2. logout-success-url属性 B.1.13.3. invalidate-session属性 B.1.14. <custom-filter>元素 B.2. 认证服务 B.2.1. <authentication-manager>元素 B.2.1.1. <authentication-provider>元素 B.2.1.2. 使用 <authentication-provider> 来引用一个 AuthenticationProvider Bean B.3. 方法安全 B.3.1. <global-method-security>元素 B.3.1.1. secured-annotations和jsr250-annotations属性 B.3.1.2. 安全方法使用<protect-pointcut> B.3.1.3. <after-invocation-provider> 元素 B.3.2. LDAP命名空间选项 B.3.2.1. 使用<ldap-server>元素定义LDAP服务器 B.3.2.2. <ldap-provider>元素 B.3.2.3. <ldap-user-service>元素
Spring Security 参考 1 第一部分前言 15 1.入门 16 2.介绍 17 2.1什么是Spring Security? 17 2.2历史 19 2.3版本编号 20 2.4获得Spring安全 21 2.4.1使用Maven 21 Maven仓库 21 Spring框架 22 2.4.2 Gradle 23 Gradle存储库 23 使用Spring 4.0.x和Gradle 24 2.4.3项目模块 25 核心 - spring-security-core.jar 25 远程处理 - spring-security-remoting.jar 25 Web - spring-security-web.jar 25 配置 - spring-security-config.jar 26 LDAP - spring-security-ldap.jar 26 ACL - spring-security-acl.jar 26 CAS - spring-security-cas.jar 26 OpenID - spring-security-openid.jar 26 测试 - spring-security-test.jar 26 2.4.4检出来源 26 3. Spring Security 4.2的新特性 27 3.1 Web改进 27 3.2配置改进 28 3.3杂项 28 4.样品和指南(从这里开始) 28 5. Java配置 29 5.1 Hello Web安全Java配置 29 5.1.1 AbstractSecurityWebApplicationInitializer 31 5.1.2 AbstractSecurityWebApplicationInitializer不存在Spring 31 5.1.3使用Spring MVC的AbstractSecurityWebApplicationInitializer 32 5.2 HttpSecurity 32 5.3 Java配置和表单登录 34 5.4授权请求 35 5.5处理注销 36 5.5.1 LogoutHandler 37 5.5.2 LogoutSuccessHandler 37 5.5.3更多注销相关参考 38 5.6认证 38 5.6.1内存认证 38 5.6.2 JDBC认证 39 5.6.3 LDAP认证 39 5.6.4 AuthenticationProvider 41 5.6.5 UserDetailsService 41 5.6.6 LDAP认证 41 5.7多个HttpSecurity 41 5.8方法安全性 43 5.8.1 EnableGlobalMethodSecurity 43 5.8.2 GlobalMethodSecurityConfiguration 44 5.9后处理配置的对象 45 5.10自定义DSL 46 6.安全命名空间配置 47 6.1简介 47 6.1.1命名空间的设计 49 6.2安全命名空间配置入门 50 6.2.1 web.xml配置 50 6.2.2最小的配置 50 6.2.3表单和基本登录选项 52 设置默认的登录目的地 54 6.2.4注销处理 54 6.2.5使用其他身份验证提供程序 55 添加密码编码器 56 6.3高级Web功能 56 6.3.1记得我认证 56 6.3.2添加HTTP / HTTPS通道安全 57 6.3.3会话管理 57 检测超时 57 并发会话控制 58 会话固定攻击保护 59 6.3.4 OpenID支持 60 属性交换 61 6.3.5响应头 62 6.3.6添加你自己的过滤器 62 设置一个自定义的AuthenticationEntryPoint 64 6.4方法安全 64 6.4.1 元素 65 使用protect-pointcut添加安全性切入点 66 6.5默认AccessDecisionManager 67 6.5.1自定义AccessDecisionManager 67 6.6验证管理器和命名空间 67 7.示例应用程序 69 7.1教程示例 69 7.2联系人 69 7.3 LDAP样本 71 7.4 OpenID示例 71 7.5 CAS样品 71 7.6 JAAS样品 72 7.7预认证样本 72 8. Spring Security社区 72 8.1问题跟踪 72 8.2成为参与 73 8.3更多信息 73 第二部分 架构与实现 73 9.技术概述 73 9.1运行环境 73 9.2核心组件 74 9.2.1 SecurityContextHolder,SecurityContext和认证对象 74 获取有关当前用户的信息 75 9.2.2 UserDetailsService 75 9.2.3授予权力 77 9.2.4总结 77 9.3认证 78 9.3.1什么是Spring Security中的认证? 78 9.3.2直接设置SecurityContextHolder内容 80 9.4 Web应用程序中的身份验证 81 9.4.1 ExceptionTranslationFilter 82 9.4.2 AuthenticationEntryPoint 82 9.4.3认证机制 82 9.4.4在请求之间存储SecurityContext 83 9.5 Spring Security中的访问控制(授权) 84 9.5.1安全和AOP建议 84 9.5.2安全对象和AbstractSecurityInterceptor 85 什么是配置属性? 85 RunAsManager 86 AfterInvocationManager 86 扩展安全对象模型 87 9.6本地化 87 10.核心服务 89 10.1 AuthenticationManager,ProviderManager和AuthenticationProvider 89 10.1.1成功认证时清除证书 91 10.1.2 DaoAuthenticationProvider 91 10.2 UserDetailsService实现 92 10.2.1内存认证 92 10.2.2 JdbcDaoImpl 93 权威组织 94 10.3密码编码 94 10.3.1什么是散列? 95 10.3.2添加盐到哈希 95 10.3.3散列和认证 96 10.4Jackson 支持 96 第三部分 测试 97 11.测试方法安全性 97 11.1安全测试设置 98 11.2 @WithMockUser 98 11.3 @WithAnonymousUser 100 11.4 @用户详细信息 101 11.5 @WithSecurityContext 102 11.6测试元注释 104 12. Spring MVC测试集成 104 12.1设置MockMvc和Spring Security 104 12.2 SecurityMockMvcRequestPostProcessors 105 12.2.1使用CSRF保护进行测试 105 12.2.2在Spring MVC测试中以用户身份运行测试 106 12.2.3使用RequestPostProcessor在Spring MVC测试中以用户身份运行 106 作为用户在Spring MVC测试中使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的认证 109 12.3.2测试注销 110 12.4 SecurityMockMvcResultMatchers 110 12.4.1未经认证的声明 111 12.4.2认证断言 111 第四部分 Web应用程序安全 112 13.安全过滤器链 112 13.1 DelegatingFilterProxy 112 13.2 FilterChainProxy 113 13.2.1绕过滤网链 115 13.3过滤器排序 115 13.4请求匹配和HttpFirewall 116 13.5与其他基于过滤器的框架一起使用 118 13.6高级命名空间配置 118 14.核心安全筛选器 119 14.1 FilterSecurityInterceptor 119 14.2 ExceptionTranslationFilter 121 14.2.1 AuthenticationEntryPoint 122 14.2.2 AccessDeniedHandler 122 14.2.3 SavedRequest和RequestCache接口 123 14.3 SecurityContextPersistenceFilter 123 14.3.1 SecurityContextRepository 124 14.4 UsernamePasswordAuthenticationFilter 125 14.4.1认证成功与失败的应用流程 125 15. Servlet API集成 127 15.1 Servlet 2.5+集成 127 15.1.1 HttpServletRequest.getRemoteUser() 127 15.1.2 HttpServletRequest.getUserPrincipal() 127 15.1.3 HttpServletRequest.isUserInRole(String) 128 15.2 Servlet 3+集成 128 15.2.1 HttpServletRequest.authenticate(HttpServletResponse) 128 15.2.2 HttpServletRequest.login(String,String) 129 15.2.3 HttpServletRequest.logout() 129 15.2.4 AsyncContext.start(Runnable) 129 15.2.5异步Servlet支持 130 15.3 Servlet 3.1+集成 131 15.3.1 HttpServletRequest#changeSessionId() 132 16.基本和摘要式身份验证 132 16.1 BasicAuthenticationFilter 132 16.1.1配置 132 16.2 DigestAuthenticationFilter 133 16.2.1配置 135 17.记住我的身份验证 136 17.1概述 136 17.2简单的基于哈希的令牌方法 136 17.3持久性令牌方法 137 17.4记住我的接口和实现 138 17.4.1 TokenBasedRememberMeServices 138 17.4.2 PersistentTokenBasedRememberMeServices 139 18.跨站点请求伪造(CSRF) 140 18.1 CSRF攻击 140 18.2同步器令牌模式 141 18.3何时使用CSRF保护 142 18.3.1 CSRF保护和JSON 142 18.3.2 CSRF和无状态浏览器应用程序 143 18.4使用Spring Security CSRF保护 143 18.4.1使用适当的HTTP动词 144 18.4.2配置CSRF保护 144 18.4.3包含CSRF令牌 145 表单提交 145 Ajax和JSON请求 145 CookieCsrfTokenRepository 146 18.5 CSRF警告 147 18.5.1超时 148 18.5.2登录 148 18.5.3注销 149 18.5.4多部分(文件上传) 149 在Spring Security之前放置MultipartFilter 150 包含CSRF令牌 151 18.5.5隐藏的HttpMethodFilter 151 18.6覆盖默认值 151 19. CORS 152 20.安全性HTTP响应头 154 20.1默认的安全头 154 20.1.1缓存控制 157 20.1.2内容类型选项 158 20.1.3 HTTP严格传输安全(HSTS) 159 20.1.4 HTTP公钥密码(HPKP) 161 20.1.5 X-Frame-Options 163 20.1.6 X-XSS保护 164 20.1.7内容安全策略(CSP) 165 配置内容安全策略 166 其他资源 168 20.1.8推荐人政策 168 配置引用者策略 169 20.2自定义标题 169 20.2.1静态头 169 20.2.2标题作者 170 20.2.3 DelegatingRequestMatcherHeaderWriter 171 21.会议管理 172 21.1 SessionManagementFilter 173 21.2 SessionAuthenticationStrategy 173 21.3并发控制 174 21.3.1查询当前通过身份验证的用户及其会话的SessionRegistry 176 22.匿名身份验证 177 22.1概述 177 22.2配置 178 22.3 AuthenticationTrustResolver 179 23. WebSocket安全 180 23.1 WebSocket配置 181 23.2 WebSocket身份验证 182 23.3 WebSocket授权 182 23.3.1 WebSocket授权说明 183 消息类型的WebSocket授权 184 目的地上的WebSocket授权 184 23.3.2出站消息 185 23.4执行相同的来源政策 185 23.4.1为什么同源? 185 23.4.2 Spring WebSocket允许的来源 186 23.4.3添加CSRF到Stomp头 186 23.4.4在WebSockets中禁用CSRF 187 23.5使用SockJS 187 23.5.1 SockJS和框架选项 187 23.5.2轻松放松CSRF 188 第五部分授权 190 24.授权体系结构 190 24.1当局 190 24.2预调用处理 191 24.2.1 AccessDecisionManager 191 24.2.2基于投票的AccessDecisionManager实现 192 RoleVoter 193 AuthenticatedVoter 194 自定义选民 194 24.3调用处理后 194 24.4分层角色 196 25.安全的对象实现 197 25.1 AOP联盟(MethodInvocation)安全拦截器 197 25.1.1显式MethodSecurityInterceptor配置 197 25.2 AspectJ(JoinPoint)安全拦截器 198 26.基于表达式的访问控制 200 26.1概述 200 26.1.1通用内置表达式 201 26.2网络安全表达式 202 26.2.1在Web安全表达式中引用Bean 203 26.2.2 Web安全表达式中的路径变量 204 26.3方法安全表达式 204 26.3.1 @Pre和@Post注释 205 访问控制使用@PreAuthorize和@PostAuthorize 205 使用@PreFilter和@PostFilter进行过滤 207 26.3.2内置表达式 207 PermissionEvaluator接口 208 方法安全元注释 209 第六部分 其他主题 209 27.域对象安全(ACL) 209 27.1概述 209 27.2重要概念 211 27.3入门 214 28.预认证方案 216 28.1预认证框架类 216 28.1.1 AbstractPreAuthenticatedProcessingFilter 217 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 217 28.1.2 PreAuthenticatedAuthenticationProvider 218 28.1.3 Http403ForbiddenEntryPoint 218 28.2具体实施 219 28.2.1请求头认证(Siteminder) 219 Siteminder示例配置 219 28.2.2 Java EE容器认证 220 29. LDAP认证 220 29.1概述 220 29.2在Spring Security中使用LDAP 221 29.3配置LDAP服务器 221 29.3.1使用嵌入式测试服务器 222 29.3.2使用绑定认证 222 29.3.3加载权限 223 29.4实现类 223 29.4.1 LdapAuthenticator实现 224 通用功能 224 认证者 225 PasswordComparisonAuthenticator 225 29.4.2连接到LDAP服务器 225 29.4.3 LDAP搜索对象 225 FilterBasedLdapUserSearch中 225 29.4.4 LdapAuthoritiesPopulator 226 29.4.5 Spring Bean配置 226 29.4.6 LDAP属性和定制的UserDetails 227 29.5 Active Directory认证 228 29.5.1 ActiveDirectoryLdapAuthenticationProvider 228 活动目录错误代码 229 30. JSP标签库 230 30.1声明Taglib 230 30.2授权标签 230 30.2.1禁用测试的标签授权 231 30.3认证标签 232 30.4 accesscontrollist标签 232 30.5 csrfInput标签 233 30.6 csrfMetaTags标签 233 31 Java认证授权服务(JAAS)提供者 235 31.1概述 235 31.2摘要:Java认证提供者 235 31.2.1 JAAS CallbackHandler 235 31.2.2 JAAS权威机构 236 31.3 DefaultJaasAuthenticationProvider 237 31.3.1 InMemoryConfiguration 237 31.3.2 DefaultJaasAuthenticationProvider示例配置 238 31.4 JaasAuthenticationProvider 239 31.5作为主题运行 240 32. CAS认证 240 32.1概述 240 32.2 CAS的工作原理 240 32.2.1 Spring安全和CAS交互序列 241 32.3 CAS客户端的配置 244 32.3.1服务票据认证 244 32.3.2单一注销 246 32.3.3使用CAS认证无状态服务 249 配置CAS以获取代理授予票证 249 使用代理票证调用无状态服务 250 32.3.4代理票证认证 251 33. X.509认证 253 33.1概述 253 33.2将X.509身份验证添加到您的Web应用程序 253 33.3在Tomcat中设置SSL 254 34.运行认证替换 255 34.1概述 255 34.2配置 255 35. Spring Security加密模块 257 35.1简介 257 35.2加密器 257 35.2.1 BytesEncryptor 257 35.2.2 TextEncryptor 258 35.3关键发电机 258 35.3.1 BytesKeyGenerator 258 35.3.2 StringKeyGenerator 259 35.4密码编码 259 36.并发支持 260 36.1 DelegatingSecurityContextRunnable 260 36.2 DelegatingSecurityContextExecutor 262 36.3 Spring安全性并发类 264 37. Spring MVC集成 265 37.1 @EnableWebMvcSecurity 265 37.2 MvcRequestMatcher 265 37.3 @AuthenticationPrincipal 268 37.4 Spring MVC异步集成 271 37.5 Spring MVC和CSRF集成 271 37.5.1自动令牌包含 271 37.5.2解析CsrfToken 272 第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query中的安全表达式 273 第八部分 附录 274 40.安全数据库模式 274 40.1用户模式 274 40.1.1集团当局 274 40.2持久登录(记得我)架构 275 40.3 ACL模式 275 40.3.1 HyperSQL 276 40.3.2 PostgreSQL 277 40.3.3 MySQL和MariaDB 278 40.3.4 Microsoft SQL Server 279 40.3.5 Oracle数据库 280 41.安全命名空间 282 41.1 Web应用程序安全性 282 41.1.1 282 41.1.2 282 属性 283 的子元素 285 41.1.3 286 的父元素 286 属性 286 41.1.4 286 属性 287 父元素 287 41.1.5 <headers> 287 <headers>属性 288 <headers>的父元素 288 <headers>的子元素 288 41.1.6 289 属性 289 的父元素 289 41.1.7 289 属性 289 的父元素 290 41.1.8 290 属性 290 的父元素 290 41.1.9 290 的子元素 290 41.1.10 291 属性 291 的父元素 291 41.1.11 291 属性 291 的父元素 291 41.1.12 291 属性 292 的父元素 292 41.1.13 <frame-options> 292 <frame-options>属性 292 <frame-options>的父元素 293 41.1.14 [removed] 293 [removed]属性 293 [removed]的父元素 294 41.1.15 294 属性 294 的父元素 294 41.1.16 <header> 294 <header-attributes>属性 294 <header>的父元素 295 41.1.17 295 的父元素 295 属性 295 41.1.18 295 父元素 296 属性 296 41.1.19 296 的父元素 296 属性 296 41.1.20 <expression-handler> 297 <expression-handler>的父元素 297 属性 297 41.1.21 <form-login> 297 <form-login>的父元素 298 <form-login>属性 298 41.1.22 299 的父元素 300 属性 300 41.1.23 元素 300 属性 300 41.1.24 300 的父元素 300 属性 301 41.1.25 302 的父元素 302 属性 302 41.1.26 302 父元素 302 属性 303 41.1.27 303 的父元素 303 属性 303 的子元素 305 41.1.28 305 的父元素 305 属性 305 的子元素 305 41.1.29 306 的父元素 306 属性 306 41.1.30 306 的父元素 306 的子元素 307 41.1.31 307 的父元素 307 属性 307 41.1.32 307 的父元素 307 属性 307 41.1.33 元素 309 的父元素 309 属性 309 41.1.34 309 的父元素 309 属性 309 的子元素 310 41.1.35 311 的父元素 311 属性 311 41.1.36 312 的父元素 312 属性 312 41.1.37 313 属性 313 的子元素 313 41.1.38 313 的父元素 313 属性 313 41.1.39 314 属性 314 的子元素 314 41.2 WebSocket安全 314 41.2.1 315 属性 315 的子元素 316 41.2.2 316 的父元素 316 属性 316 41.3认证服务 317 41.3.1 317 属性 317 的子元素 317 41.3.2 318 的父元素 318 属性 318 的子元素 318 41.3.3 319 属性 319 41.3.4 320 的父元素 320 属性 320 的子元素 320 41.3.5 320 的父元素 321 属性 321 41.3.6 321 属性 321 的子元素 321 41.3.7 321 的父元素 322 属性 322 41.4方法安全 322 41.4.1 322 属性 322 的子元素 324 41.4.2 324 的父元素 324 属性 324 41.4.3 324 的父元素 325 325 41.4.4 325 的父元素 325 属性 325 41.4.5 325 的父元素 325 属性 325 41.4.6 326 的父元素 326 属性 326 41.4.7使用安全方法 326 父节点 326 属性 326 41.4.8 326 属性 327 的子元素 327 41.4.9 327 属性 327 的子元素 327 41.4.10 327 父元素 328 属性 328 41.5 LDAP名称空间选项 328 41.5.1使用。定义LDAP服务器 328 属性 329 41.5.2 329 的父元素 329 属性 329 的子元素 331 41.5.3 331 的父元素 331 属性 332 的子元素 332 41.5.4 332 属性 332 42.春季安全依赖 333 42.1 spring-security-core 334 42.2 spring-security-remoting 334 42.3 spring-security-web 335 42.4 spring-security-ldap 335 42.5 spring-security-config 336 42.6 spring-security-acl 336 42.7 spring-security-cas 337 42.8 spring-security-openid 337 42.9 spring-security-taglibs 338 43.代理服务器配置 338 44. Spring Security FAQ 339 44.1一般问题 339 44.1.1 Spring Security是否会处理我所有的应用程序安全要求? 339 44.1.2为什么不使用web.xml安全? 339 44.1.3需要哪些JavaSpring Framework版本? 341 44.1.4我是Spring Security的新手,我需要构建一个支持通过HTTPS进行CAS单点登录的应用程序,同时允许对某些URL进行本地基本身份验证,并对多个后端用户信息源(LDAP和JDBC)进行身份验证。我已经复制了一些我发现的配置文件,但不起作用。什么可能是错的? 341 44.2常见问题 342 44.2.1当我尝试登录时,我收到一条错误消息,指出“Bad Credentials”。怎么了? 343 44.2.2当我尝试登录时,我的应用程序进入“无限循环”,发生了什么事? 344 44.2.3我收到一条异常消息“访问被拒绝(用户是匿名的)”。怎么了? 344 44.2.4即使在我退出应用程序之后,为什么还能看到安全的页面? 345 44.2.5我得到一个异常,消息“在SecurityContext中没有找到认证对象”。怎么了? 345 44.2.6我无法使LDAP认证正常工作。我的配置有什么问题? 345 44.2.7会话管理 346 44.2.8我使用Spring Security的并发会话控制来防止用户一次登录多次。登录后打开另一个浏览器窗口时,不会阻止我再次登录。为什么我可以多次登录? 347 44.2.9为什么在通过Spring Security进行身份验证时会话ID发生了变化? 347 44.2.10我正在使用Tomcat(或其他一些servlet容器),并为我的登录页面启用了HTTPS,之后切换回HTTP。这是行不通的 - 我只是在认证之后回到登录页面。 347 44.2.11我没有在HTTP和HTTPS之间切换,但是我的会话仍然丢失 348 44.2.12我试图使用并发会话控制支持,但是不会让我重新登录,即使我确定我已经注销并且没有超出允许的会话。 348 44.2.13 Spring Security正在创建一个会话,即使我已经配置了它,通过设置create-session属性为永远不会。 348 44.2.14执行POST时,我得到了一个403 Forbidden 349 44.2.15我正在使用RequestDispatcher将请求转发到另一个URL,但是我的安全限制没有被应用。 349 44.2.16我已经将Spring Security的元素添加到我的应用程序上下文中,但是如果将安全注释添加到我的Spring MVC控制器bean(Struts操作等)中,那么它们似乎没有效果。 349 44.2.17我有一个肯定被认证的用户,但是当我在一些请求期间尝试访问SecurityContextHolder时,认证是空的。为什么我看不到用户信息? 350 44.2.18在使用URL属性时,授权JSP标记不尊重我的方法安全注释。 350 44.3 Spring安全体系结构问题 350 44.3.1我如何知道X是哪个包? 350 44.3.2名称空间元素如何映射到传统的bean配置? 351 44.3.3“ROLE_”是什么意思,为什么我的角色名字需要它? 351 44.3.4如何知道添加到我的应用程序中的哪些依赖关系与Spring Security一起使用? 352 44.3.5运行嵌入式ApacheDS LDAP服务器需要哪些依赖关系? 352 44.3.6什么是UserDetailsService,我需要一个吗? 353 44.4共同的“Howto”请求 353 44.4.1我需要登录更多的信息,而不仅仅是用户名。如何添加对额外登录字段(例如公司名称)的支持? 354 44.4.2如果只有所请求的URL的片段值不同(例如/ foo#bar和/ foo#blah),我该如何应用不同的拦截url链接? 354 44.4.3如何在UserDetailsService中访问用户的IP地址(或其他Web请求数据)? 354 44.4.4如何从UserDetailsService访问HttpSession? 355 44.4.5如何在UserDetailsService中访问用户的密码? 355 44.4.6如何动态定义应用程序中的安全URL? 355 44.4.7如何针对LDAP进行身份验证,但从数据库加载用户角色? 357 44.4.8我想修改由命名空间创建的bean的属性,但是模式中没有任何东西支持它。我可以做什么放弃命名空间的使用? 358 45.从3.x迁移到4.x 359

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值