java - Spring Security 中未触发 JWT 身份验证过滤器

标签 java spring spring-mvc spring-boot spring-security

我已经为 Spring Rest 后端创建了一个 JWT 身份验证过滤器。创建 JWT 似乎不是问题,但是根据我当前的设置,任何请求都会经过身份验证,尽管客户端没有在 header 中传递任何 token ,但没有请求会触发 401。

我的网络安全配置:

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

private JwtAuthenticationEntryPoint unauthorizedHandler;

private CustomUserDetailsService customUserDetailsService;

@Autowired
public WebSecurityConfig(final JwtAuthenticationEntryPoint unauthorizedHandler,
                         final CustomUserDetailsService customUserDetailsService) {
    this.unauthorizedHandler = unauthorizedHandler;
    this.customUserDetailsService = customUserDetailsService;
}

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
    return new JwtAuthenticationFilter();
}

@Bean
public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() {
    return new JwtAuthenticationSuccessHandler();
}

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder
            .userDetailsService(customUserDetailsService)
            .passwordEncoder(passwordEncoder());
}

@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

/**
 * {@inheritDoc}
 */
@Override
protected void configure(final HttpSecurity http) throws Exception {

    http
            .csrf()
            .disable()
            .cors()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(unauthorizedHandler)
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .antMatcher("/api")
            .authorizeRequests()
            .anyRequest()
            .authenticated()

            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}

/**
 * Sets security evaluation context.
 *
 * @return {@link SecurityEvaluationContextExtension}
 */
@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();
}
}

我已将其设置为所有请求都需要授权。我的 JwtAuthenticationEntryPoint 与预期一致:抛出一般 401 错误。

我的 JwtAuthenticationFilter:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtTokenProvider tokenProvider;

@Autowired
private CustomUserDetailsService customUserDetailsService;

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

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain
        filterChain) throws ServletException, IOException {

    logger.debug("Filtering request for JWT header verification");

    try {
        String jwt = getJwtFromRequest(request);

        if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
            String username = tokenProvider.getUserIdFromJWT(jwt);

            UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken
                    (userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (Exception ex) {
        logger.error("Could not set user authentication in security context", ex);
    }

    filterChain.doFilter(request, response);
}

private String getJwtFromRequest(HttpServletRequest request) {

    logger.debug("Attempting to get token from request header");

    String bearerToken = request.getHeader("Authorization");
    if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
        return bearerToken.substring(7, bearerToken.length());
    }
    return null;
}
 }

最佳答案

发现问题了。

我必须在 web.xml 文件中包含对过滤器的引用,这不会使用组件扫描器自动获取。

类似于:

<filter>
    <filter-name>jwtFilter</filter-name>
    <filter-class>com.path.to.JwtFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>jwtFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

关于java - Spring Security 中未触发 JWT 身份验证过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51002289/

相关文章:

Java 属性类附加日期

java - Java 中枚举最常见的用法是什么?

spring - 为什么我们在 Spring Java Configuration 中有 *Adapter 类,而它们不是一般意义上的 Adapter

spring-mvc - Spring MVC 测试用例

java - 在 2.3.4 中序列化 DecimalFormatSymbols 时出现问题

java - 收件人列表路由器 Spring 集成

spring - DBUNIT 和 Spring.. 无法加载数据集文件

java - 可以使用 InterfaceBasedMBeanInfoAssembler 为 Spring JMX MBean 设置描述吗?

java - Spring MVC 项目上的“缺少 Artifact ”和 'Failed to read artifact descriptor' 错误

java - 带下划线的hibernate中生成的列名和表名