zoukankan      html  css  js  c++  java
  • SpringSecurity过滤器顺序(转)

    SpringSecurity过滤器顺序

    官网地址 

    官网定义的关键过滤器顺序:

     

    源码里所有的过滤器顺序:

     

    默认情况会启动以下过滤器:

    (默认设置在:WebSecurityConfigurerAdapter 的  getHttp()方法里)

     

    怎么替换默认的过滤器: 

    http.addFilterAt() 不能替换默认的过滤器,只是在相同的位置放置一个过滤器,原本的过滤器仍然起作用

    可以disable掉默认的过滤器,例如用自定义的登出过滤器

    http.logout().disable();

    http.addFilterAt(new MyLogoutFilter(), LogoutFilter.class);

    部分过滤器的含义:

    ChannelProcessingFilter:转换协议时使用,例如将http重定向到https

    ConcurrentSessionFilter:判断session是否过期以及更新最新访问时间

    SecurityContextPersistenceFilter:将用户信息绑定到线程

    这样全局可通过SecurityContextHolder.getContext().getAuthentication()拿到用户信息

    注:如果要拿到request/response信息(这个不是过滤器设置的,是框架默认会绑定到线程)

    可通过((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()

    HeaderWriterFilter:默认增加以下头部信息

    X-Content-Type-Options: nosniff
    X-XSS-Protection: 1; mode=block
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0
    X-Frame-Options: DENY

    关闭:http.headers().disable();

    只保留缓存控制:http.headers().defaultsDisabled().cacheControl()

    注:详细描述可查看官网地址

    X-Content-Type-Options: nosniff 表示浏览器必须且只能根据Content-Type字段分辨资源类型(浏览器默认会 猜测资源类型)

    X-XSS-Protection:防范XSS攻击

    • 0:禁用XSS保护;
    • 1:启用XSS保护;
    • 1; mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);

    X-Frame-Options:是否允许页面被嵌套

    DENY  表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许
    SAMEORIGIN  表示该页面可以在相同域名页面的 frame 中展示
    ALLOW-FROM uri  表示该页面可以在指定来源的 frame 中展示

    Cache-Control/Pragma/Expires:缓存控制(简单描述

    CorsFilter: 配置跨域

    1.  
      @Override
    2.  
      protected void configure(HttpSecurity http) throws Exception {
    3.  
      http
    4.  
      // by default uses a Bean by the name of corsConfigurationSource
    5.  
      .cors().and()
    6.  
      ...
    7.  
      }
    8.  
       
    9.  
      @Bean
    10.  
      CorsConfigurationSource corsConfigurationSource() {
    11.  
      CorsConfiguration configuration = new CorsConfiguration();
    12.  
      configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
    13.  
      configuration.setAllowedMethods(Arrays.asList("GET","POST"));
    14.  
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    15.  
      source.registerCorsConfiguration("/**", configuration);
    16.  
      return source;
    17.  
      }

    CsrfFilter: 防止Csrf攻击,通过配置与Session绑定的token,每次请求都需要携带最新的token

    注:默认是在前后端不分离的情况下,通过jsp/ft等传递到前端。在前后端分离的情况下,可以增加过滤器使其配置在 json/或者头部

    LogoutFilter:配置登出的处理 一般可设置登出成功的处理,删除cookie,使Session无效等

    UsernamePasswordAuthenticationFilter:验证登录,并可以配置登录成功/失败的处理

    1.  
      http.formLogin() // 表单登录
    2.  
      // 登录的界面,前后端分离时不需要这个配置。没登录去访问系统资源时会重定向到这个界面
    3.  
      .loginPage("/login/home")
    4.  
      // 登录验证,框架自动实现
    5.  
      .loginProcessingUrl("/login/verify")
    6.  
      // 如果直接访问的是登录界面login1,返回的URL,否则会返回重定向到原本请求的URL
    7.  
      .successHandler(myAuthenticationSuccessHandler)
    8.  
      // 失败返回的URL
    9.  
      .failureHandler(myAuthenticationFailureHandler)

    SecurityContextHolderAwareRequestFilter: 包装类,实现HttpServletRequest的getAuthentication getRemoteUser等方法

    RememberMeAuthenticationFilter: 配置rememberMe,比如7天之内不需要登录

    当拿不到用户信息时(SecurityContextHolder.getContext()为空),会去找key是remember-me的Cookie配置用户信息

    AnonymousAuthenticationFilter:没有通过username和remember认证的用户赋予匿名身份

    SessionManagementFilter:session管理:限制同一用户开启多个会话的数量

    ExceptionTranslationFilter:一般其只处理两大类异常:

    AccessDeniedException访问权限异常

    AuthenticationException用户认证异常:包括匿名用户异常

    配置自定义的401和403异常处理:

    1.  
       http.exceptionHandling()
    2.  
                      .accessDeniedHandler(new MyAccessDeniedHandler())
    3.  
                      .authenticationEntryPoint(new MyAuthenticationEntryPoint());

    FilterSecurityInterceptor :拿到用户的权限(从SecurityContextHolder中获取Authentication对象)和资源所需权限(SecurityMetadataSource),在AccessDecisionManager里对比看用户是否有权限

    注:

    CsrfFilter类

    1.  
      @Override
    2.  
      protected void doFilterInternal(HttpServletRequest request,
    3.  
      HttpServletResponse response, FilterChain filterChain)
    4.  
      throws ServletException, IOException {
    5.  
      request.setAttribute(HttpServletResponse.class.getName(), response);
    6.  
      // 获取与session绑定的csrfToken,没有就新建一个
    7.  
      CsrfToken csrfToken = this.tokenRepository.loadToken(request);
    8.  
      final boolean missingToken = csrfToken == null;
    9.  
      if (missingToken) {
    10.  
      csrfToken = this.tokenRepository.generateToken(request);
    11.  
      this.tokenRepository.saveToken(csrfToken, request, response);
    12.  
      }
    13.  
       
    14.  
      request.setAttribute(CsrfToken.class.getName(), csrfToken);
    15.  
      request.setAttribute(csrfToken.getParameterName(), csrfToken);
    16.  
       
    17.  
      // 如果不是与csrf相关的请求就直接跳过
    18.  
      if (!this.requireCsrfProtectionMatcher.matches(request)) {
    19.  
      filterChain.doFilter(request, response);
    20.  
      return;
    21.  
      }
    22.  
      // 否则直接比对 头部/表单里的csrfToken 和 session绑定的CsrfToken
    23.  
      String actualToken = request.getHeader(csrfToken.getHeaderName());
    24.  
      if (actualToken == null) {
    25.  
      actualToken = request.getParameter(csrfToken.getParameterName());
    26.  
      }
    27.  
      if (!csrfToken.getToken().equals(actualToken)) {
    28.  
      if (this.logger.isDebugEnabled()) {
    29.  
      this.logger.debug("Invalid CSRF token found for "
    30.  
      + UrlUtils.buildFullRequestUrl(request));
    31.  
      }
    32.  
      if (missingToken) {
    33.  
      this.accessDeniedHandler.handle(request, response,
    34.  
      new MissingCsrfTokenException(actualToken));
    35.  
      }
    36.  
      else {
    37.  
      this.accessDeniedHandler.handle(request, response,
    38.  
      new InvalidCsrfTokenException(csrfToken, actualToken));
    39.  
      }
    40.  
      return;
    41.  
      }
    42.  
       
    43.  
      filterChain.doFilter(request, response);
    44.  
      }
  • 相关阅读:
    Java字符串比较
    Java中定义不了可变长数组怎么办---集合 泛型
    Java后台读取excel表格返回至Web前端
    JAVA中Stringbuffer的append( )方法
    Java操作Excel中HSSFCell.CELL_TYPE_STRING、BOOLEAN、NUMERIC无定义解决方法
    数据结构---公交线路提示系统05(内附读取表格+迪杰斯特拉算法Java代码)
    .getCellType()的几种类型值
    数据结构---公交线路提示系统04
    数据结构---公交线路提示系统03
    转载一篇较为详细的caffe-ssd编译环境的搭建
  • 原文地址:https://www.cnblogs.com/yasepix/p/14185895.html
Copyright © 2011-2022 走看看