【问题标题】:Add http security filter in java config在 java config 中添加 http 安全过滤器
【发布时间】:2013-11-23 22:08:50
【问题描述】:

我正在尝试在春季添加网络安全性,但我不希望过滤器应用于某些事情。在java中是怎么做到的?

也许有更好的方法来做到这一点,因为我创建了一个自定义过滤器,但由于它的依赖关系,这是我能想到实例化它的唯一方法。

总的来说,我想做的是这样的:

/resources/** 不应该通过过滤器, /login (POST) 不应该通过过滤器, 其他一切都应该通过过滤器

通过我在春季发现的各种示例,我能够想出这个作为开始,但它显然不起作用:

@Configuration
@EnableWebSecurity
@Import(MyAppConfig.class)
public class MySecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    public void configure(WebSecurity webSecurity) throws Exception
    {
        webSecurity.ignoring().antMatchers("/resources/**");
    }

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception
    {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/login").permitAll();

        httpSecurity.httpBasic();
        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    @Autowired
    public TokenFilterSecurityInterceptor<TokenInfo> tokenInfoTokenFilterSecurityInterceptor(MyTokenUserInfoCache userInfoCache, ServerStatusService serverStatusService, HttpSecurity httpSecurity) throws Exception
    {
        TokenService<TokenInfo> tokenService = new TokenServiceImpl(userInfoCache);
        TokenFilterSecurityInterceptor<TokenInfo> tokenFilter = new TokenFilterSecurityInterceptor<TokenInfo>(tokenService, serverStatusService, "RUN_ROLE");
        httpSecurity.addFilter(tokenFilter);
        return tokenFilter;
    }
}

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    您是否对忽略 URL 的所有 Spring Security 感兴趣,或者您只希望特定过滤器忽略请求?如果您希望所有 Spring Security 都忽略该请求,可以使用以下方法完成:

    @Configuration
    @EnableWebSecurity
    @Import(MyAppConfig.class)
    public class MySecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private MyTokenUserInfoCache userInfoCache;
        @Autowired
        private ServerStatusService serverStatusService;
    
        @Override
        public void configure(WebSecurity webSecurity) throws Exception
        {
            webSecurity
                .ignoring()
                    // All of Spring Security will ignore the requests
                    .antMatchers("/resources/**")
                    .antMatchers(HttpMethod.POST, "/login");
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .addFilter(tokenInfoTokenFilterSecurityInterceptor())
                .authorizeRequests()
                    // this will grant access to GET /login too do you really want that?
                    .antMatchers("/login").permitAll()
                    .and()
                .httpBasic().and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    
        @Bean
        public TokenFilterSecurityInterceptor<TokenInfo> tokenInfoTokenFilterSecurityInterceptor() throws Exception
        {
            TokenService<TokenInfo> tokenService = new TokenServiceImpl(userInfoCache);
            return new TokenFilterSecurityInterceptor<TokenInfo>(tokenService, serverStatusService, "RUN_ROLE");
        }
    }
    

    如果您只想让特定过滤器忽略特定请求,您可以执行以下操作:

    @Configuration
    @EnableWebSecurity
    @Import(MyAppConfig.class)
    public class MySecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private MyTokenUserInfoCache userInfoCache;
        @Autowired
        private ServerStatusService serverStatusService;
    
        @Override
        public void configure(WebSecurity webSecurity) throws Exception
        {
            webSecurity
                .ignoring()
                    // ... whatever is here is ignored by All of Spring Security
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .addFilter(tokenInfoTokenFilterSecurityInterceptor())
                .authorizeRequests()
                    // this will grant access to GET /login too do you really want that?
                    .antMatchers("/login").permitAll()
                    .and()
                .httpBasic().and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    
        @Bean
        public TokenFilterSecurityInterceptor<TokenInfo> tokenInfoTokenFilterSecurityInterceptor() throws Exception
        {
            TokenService<TokenInfo> tokenService = new TokenServiceImpl(userInfoCache);
            TokenFilterSecurityInterceptor tokenFilter new TokenFilterSecurityInterceptor<TokenInfo>(tokenService, serverStatusService, "RUN_ROLE");
    
    
            RequestMatcher resourcesMatcher = new AntPathRequestMatcher("/resources/**");
            RequestMatcher posLoginMatcher = new AntPathRequestMatcher("/login", "POST");
            RequestMatcher ignored = new OrRequestMatcher(resourcesMatcher, postLoginMatcher);
            return new DelegateRequestMatchingFilter(ignored, tokenService);
        }
    }
    
    
    public class DelegateRequestMatchingFilter implements Filter {
        private Filter delegate;
        private RequestMatcher ignoredRequests;
    
        public DelegateRequestMatchingFilter(RequestMatcher matcher, Filter delegate) {
            this.ignoredRequests = matcher;
            this.delegate = delegate;
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
             HttpServletRequest request = (HttpServletRequest) req;
             if(ignoredRequests.matches(request)) {
                 chain.doFilter(req,resp,chain);
             } else {
                 delegate.doFilter(req,resp,chain);
             }
        }
    }
    

    【讨论】:

    • 您不应该将 tokenFilter 而不是 tokenService 传递给您的 DelegateRequestMacingFilter 的构造函数吗?在 tokenInfoTokenFilterSecurityInterceptor 方法中,您正在创建一个过滤器,但您没有使用它。
    • 我一直在搜索是否允许将所有 URL 传递给我的自定义过滤器,如 http 基本过滤器。但我现在可以看出这是不可能的。
    • 我知道每个人都在使用它,但是我看不到 configure(HttpSecurity http) 中那个长方法链接的优势,特别是考虑到类型会随之变化。如果我们删除那些and() 并编写一个新的http.something() 语句,一切(更多)不是更清楚吗?我在这里错过了什么?
    • @Rob Winch 我们有一个问题,如果 webSecurity.ignoring() 正在工作,那么为什么我们需要自定义逻辑来忽略给定的 url。知道为什么 webSecurity.ignoring() 不起作用。
    【解决方案2】:

    1 在我使用的spring-security的xml配置中

    <http pattern="/resources/**" security="none"/> 
    
    <http use-expressions="true">
    <intercept-url pattern="/login" access="permitAll"/> 
    </http>    
    

    从安全检查中检索它。

    2 然后在你的spring配置中添加mvc:resource标签

    <mvc:resources mapping="/resource/**" location="/resource/"/>
    

    重要提示:此配置仅在 url 由调度程序 servlet 处理时才有效。这意味着在 web.xml 中你必须有

       <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping> 
    

    【讨论】:

    • 嗯,我有一个类似的 xml 配置用于不同的应用程序,但出于各种原因,我真的想在 java 中这样做。问题是支持java配置的spring security版本是3.2.0.RC2所以它甚至还没有发布......
    猜你喜欢
    • 2021-12-31
    • 2017-05-18
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    相关资源
    最近更新 更多