弹簧安全 AntMatcher 不工作

Posted

技术标签:

【中文标题】弹簧安全 AntMatcher 不工作【英文标题】:Spring security AntMatcher is not working 【发布时间】:2018-09-28 13:15:15 【问题描述】:

这是我配置 Spring Security 的方式,在控制器中我获得 ROLE_ANONYMOUS 作为权限。看起来安全性没有拦截请求并检查 JWT。 如何配置antmatcher..?

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter


   @Override
   public void configure(HttpSecurity http) throws Exception
   
      http.authorizeRequests()
            .antMatchers("/actuator/**", "/api-docs/**").permitAll()
            .antMatchers("/notes/**").hasAnyAuthority("USER").anyRequest().authenticated();
   


下面是我的控制器代码

@RestController
@RequestMapping("/notes")
public class NoteController

   @Autowired
   private IUserService userService;

   @Autowired
   private INoteService noteService;

   static MessageSourceAccessor messageAccesser =  ApplicationConfiguration.getMessageAccessor();

   private final Logger logger = LoggerFactory.getLogger(NoteController.class);

   @RequestMapping(value = "/addnote", method = RequestMethod.POST)
   public ResponseEntity<Response> addNote(@RequestBody NoteDto note, HttpSession session)
   
      Authentication ath = SecurityContextHolder.getContext().getAuthentication();
      int userId = 5;
      logger.debug("Adding note :-", note);
      Response response = new Response();
      try 
         User user = userService.getUserById(userId);
         if (user == null) 
            response.setStatus(111);
            response.setResponseMessage(ApplicationConfiguration.getMessageAccessor().getMessage("111"));
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
         
         noteService.saveNote(note, user);

       catch (Exception e) 
         logger.error(e.getMessage());
         FNException fn = new FNException(101, new Object[]  "Adding Note - " + e.getMessage() , e);
         return new ResponseEntity<>(fn.getErrorResponse(), HttpStatus.INTERNAL_SERVER_ERROR);
      
      response.setStatus(200);
      response.setResponseMessage(messageAccesser.getMessage("200"));
      return new ResponseEntity<>(response, HttpStatus.OK);
   

更新 看起来antmatchers不起作用。这是我点击 api 时的日志。

DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.s.w.u.matcher.OrRequestMatcher.matches line: 72 - No matches found
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 5 of 10 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 6 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 7 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 8 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.s.w.a.AnonymousAuthenticationFilter.doFilter line: 100 - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 9 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.s.w.s.SessionManagementFilter.doFilter line: 124 - Requested session ID DE97FB345788E4AB200B922552573A31 is invalid.
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 325 - /notes/addnote at position 10 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.security.web.FilterChainProxy.doFilter line: 310 - /notes/addnote reached end of additional filter chain; proceeding with original chain
DEBUG [http-nio-8080-exec-3]: 2018-04-18 16:31:03 o.s.web.servlet.DispatcherServlet.doService line: 869 - DispatcherServlet with name 'dispatcherServlet' processing POST request for [/notes/addnote]

【问题讨论】:

你还有其他低阶的Spring Security配置吗?解决您的问题的最佳方法是,将具有 DEBUG 级别的 Spring Security 日志添加到您的问题中。它会显示原因。 看起来 antmatcher 无法正常工作。我已经添加了有问题的日志。请检查。 不幸的是,您必须提供更多日志。目前尚不清楚执行哪个过滤器链。 Spring Boot 有很多过滤器链(静态资源、授权服务器、资源服务器、Spring Boot 默认、Actuator、...) 您是否有理由特别需要使用ResourceServerConfigurerAdapter 而不是WebSecurityConfigurerAdapter 【参考方案1】:

试试WebSecurityConfigurerAdapter,你可以参考我下面的demo。我自定义了一些过滤器进行验证,如果您不需要,只需将其删除。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
        auth.authenticationProvider(authenticationProvider());
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable();
        http.addFilterBefore(new CaptchaAuthenticationFilter("/login", "/login?error2"), UsernamePasswordAuthenticationFilter.class);
        http.authorizeRequests()
                .antMatchers("/").hasRole("USER")
                .antMatchers("/index").hasRole("USER")
                .antMatchers("/message/*").hasRole("USER")
                .anyRequest().permitAll()
                .and().formLogin().loginPage("/login").defaultSuccessUrl("/index").failureUrl("/login?error1").permitAll()
                .and().rememberMe().tokenValiditySeconds(60*60*7).key("message")
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
    

    @Bean
    public AuthenticationProvider authenticationProvider()
        DaoAuthenticationProvider authenticationProvider=new CustomAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService());
        return authenticationProvider;
    

    @Bean
    public UserDetailsService userDetailsService()
        return new CustomUserDetailService();
    


【讨论】:

【参考方案2】:

你使用的是什么版本的 spring-boot 和 spring-security?

@EnableResourceServer 注解自动将 OAuth2AuthenticationProcessingFilter 类型的过滤器添加到 Spring Security 过滤器链中。

所以要在 OAuth2AuthenticationProcessingFilter 之前应用您的“扩展 ResourceServerConfigurerAdapter”,您需要使用 @Order (-1) 对其进行注释

@Configuration
@EnableResourceServer
@Order(-1)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
[...]

【讨论】:

我使用的是 spring boot 1.5.9.RELEASE。而且它仍然无法使用@Order(-1)

以上是关于弹簧安全 AntMatcher 不工作的主要内容,如果未能解决你的问题,请参考以下文章

允许通过Spring Web安全性限制访问安全资源

弹簧安全返回 403,日志记录不起作用

Spring Security:antMatcher 的序列未按预期工作 [重复]

Spring security antMatcher 未按预期工作

没有弹簧安全性的 ldap 和 JWT 身份验证

弹簧 websocket 没有弹簧安全