PermitAll 在 Spring Security 中不起作用

Posted

技术标签:

【中文标题】PermitAll 在 Spring Security 中不起作用【英文标题】:PermitAll not working in Spring Security 【发布时间】:2017-08-20 09:41:20 【问题描述】:

我有两个规则,第一个来自 oauth/** 的每个 url 应该没有安全性,其他 url 必须安全。但现在所有 url 都是安全的,包括来自 oauth/** 的 url。 这是我的安全配置规则。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 
        // JWT dont need CSRF
        httpSecurity.csrf().disable().exceptionHandling().and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
                .antMatchers("oauth/**").permitAll().and()
                .addFilterBefore(new JwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class);

        // disable page caching
        httpSecurity.headers().cacheControl();
    


当我请求进入我的 JwtAuthenticationTokenFilter 的 url http://localhost:8080/oauth/fb 时,我希望这个 url 不要进入这个过滤器。

【问题讨论】:

【参考方案1】:

您可以使用 WebSecurity 参数覆盖配置方法。

@Override
public void configure(final WebSecurity web) throws Exception

    web.ignoring().antMatchers("oauth/**");

在提供文档中建议的静态内容(例如 css/* js/*)时应该使用此方法,但是我找不到另一种方法来允许在 Spring Security 中使用自定义过滤器进行 URL 映射。

【讨论】:

这很可悲。它应该改变。【参考方案2】:
<security:http pattern="/support/**" security="none"/>

您可能需要编写与上述 XML 配置等效的 Java。基本上,您正在为上述模式设置一个没有安全性的新过滤器链。

【讨论】:

我用的是spring boot,我不使用XML来配置。【参考方案3】:

我遇到了类似的问题。我的安全配置:

// ... imports
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    private final UserDetailsService userDetailsService;
    private final PasswordEncoder passwordEncoder;
    private final JwtFilter jwtFilter;

    @Autowired
    public SecurityConfig(@Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService,
                          PasswordEncoder passwordEncoder,
                          JwtProvider jwtProvider) 
        this.userDetailsService = userDetailsService;
        this.passwordEncoder = passwordEncoder;
        this.jwtFilter = new JwtFilter(jwtProvider);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .csrf().disable()
                .httpBasic().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/auth/**").permitAll()
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    

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

    protected DaoAuthenticationProvider daoAuthenticationProvider() 
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return provider;
    

还有我的安全过滤器:

// ... imports
public class JwtFilter extends GenericFilterBean 
    public static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final int TOKEN_START_POSITION = 7;

    private final JwtProvider jwtProvider;

    @Autowired
    public JwtFilter(JwtProvider jwtProvider) 
        this.jwtProvider = jwtProvider;
    

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException 
        String token = getTokenFromRequest((HttpServletRequest) servletRequest);
        if (token != null && jwtProvider.validateToken(token)) 
            Map<String, Object> properties = jwtProvider.getUserPropertiesFromToken(token);
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                    properties.get("login"),
                    null,
                    (Set<GrantedAuthority>) properties.get("authirities"));
            SecurityContextHolder.getContext().setAuthentication(auth);
        
        filterChain.doFilter(servletRequest, servletResponse);
    

    private String getTokenFromRequest(HttpServletRequest request) 
        String bearer = request.getHeader(AUTHORIZATION_HEADER);
        if (bearer != null && bearer.startsWith(TOKEN_PREFIX)) 
            return bearer.substring(TOKEN_START_POSITION);
        
        return null;
    

我的代码对我不起作用的原因是我在过滤器中跳过了 filterChain.doFilter(servletRequest, servletResponse); 行,即我没有将请求和响应传递给链中的下一个实体。

【讨论】:

以上是关于PermitAll 在 Spring Security 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

PermitAll 在 Spring Security 中不起作用

Spring Boot permitAll 在 WebSecurityConfigurerAdapter 中不起作用

尽管 authorizeRequests().anyRequest().permitAll() spring-security 返回 401

Spring Security中permitAll()和anonymous()的区别

Spring 安全性不允许使用简单的匹配器和 permitAll 进行访问

如何在 Spring Security 中获取 permitAll 以不在 @Controller 对象中抛出 AuthenticationCredentialsNotFoundException?