春季安全性:仅将过滤器应用于端点

时间:2019-01-11 12:25:44

标签: spring spring-boot spring-security

目前,我在服务中使用了两种端点:

  • /portal/**:我需要添加过滤器PortalAuthorizationFilter
  • 其他:我需要添加一个过滤器OthersAuthorizationFilter

重要的是,OthersFilter不应应用于/portal/**呼叫。

我已经创建了WebSecurityConfigurerAdapter。我当前的代码是:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .addFilterBefore(new JWTExceptionHandlerFilter(objectMapper, messageSource), BasicAuthenticationFilter.class)
            .cors().and()
            .csrf().disable()
            .antMatcher("/portal/**")
            .addFilter(new PortalAuthorizationFilter())
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .addFilter(new OthersAuthorizationFilter());
    }
}

调用/portal/**,到达PortalAuthorizationFilter但又到达OthersAuthorizationFilter时,我已经调试了这段代码。

我不太想怎么解决。

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

您需要创建另一个配置类,该类还将扩展WebSecurityConfigurerAdapter,在那里您将url与antMatchers匹配并添加过滤器。无论哪种模式匹配都将运行该安全配置 阅读此post

答案 1 :(得分:0)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/portal/**").... //the configuration only 
              //applies when sb hitting /portal/**
    }
}

如果您想为另一个网址进行其他配置,则需要覆盖另一个WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@Order(101) //@Order(100) is default
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http... //without antMatcher(...) default will be used "/**", 
                //so it take all request. So the order of this class should be 
                // higher
    }
}

如果您想使用过滤器方法(.addFilter(new OthersAuthorizationFilter());,那么在您的doFilter方法中,您应该实现:

doFilter(...) {
  if(match(request, "/portal/**")
    ....
}

不幸的是,AuthenticationProvider不会给您这种可能性,它不知道url,而只是凭据。如果您想要更多read spring-security-architecture

但是我想你to delegate authorization

答案 2 :(得分:0)

另一个选择是使用委托模式。想象一下,如果您有一个看起来像这样的过滤器

public class PickAndChooseFilter extends OncePerRequestFilter {

    private AntPathRequestMatcher matcher = new AntPathRequestMatcher("/portal/**");
    private final Filter portalAuthorizationFilter;
    private final Filter othersAuthorizationFilter;

    public PickAndChooseFilter(Filter portalAuthorizationFilter, Filter othersAuthorizationFilter) {
        this.portalAuthorizationFilter = portalAuthorizationFilter;
        this.othersAuthorizationFilter = othersAuthorizationFilter;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        if (matcher.matches(request)) {
            portalAuthorizationFilter.doFilter(request, response, filterChain);
        } else {
            othersAuthorizationFilter.doFilter(request, response, filterChain);
        }
    }
}

然后代替

.addFilter(new PortalAuthorizationFilter())
.addFilter(new OthersAuthorizationFilter())

您只需拥有

.addFilter(new PickAndChooseFilter(
    new PortalAuthorizationFilter(),
    new OthersAuthorizationFilter()
)