繁体   English   中英

使用 jwt 在 springboot 中始终允许未经授权的请求

[英]unauthorized request are always allowed in springboot using jwt

我有一个项目,我启用了 jwt 对其进行授权。 问题是,每当我发送一个空的 header 请求或 header 中的过期授权码时,它不会向我发送未经授权的错误,它会在日志中显示令牌无效但允许请求继续工作。 这是我的配置代码:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    @Autowired
    private UserDetailsService jwtUserDetailsService;
    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(BCryptVersion.$2Y);
    }

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

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()

                .authorizeRequests().antMatchers("/authenticate","/user","/swagger-ui.html","/swagger-ui/**"
                ,"/v3/api-docs/**").permitAll().

                anyRequest().authenticated().and().

                exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()

                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        httpSecurity.logout().logoutSuccessUrl("/authenticate").logoutUrl("/logout").permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers(String.valueOf(HttpMethod.OPTIONS), "/**");
        // ignore swagger
        web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs");
    }
}

这是我的 jwt 请求过滤器:

@Component
public class JwtRequestFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    private JwtTokenUtil jwtTokenUtil;

    public JwtRequestFilter(JwtTokenUtil jwtTokenUtil) {
        this.jwtTokenUtil = jwtTokenUtil;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader("Authorization");
        String username = null;
        String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {

            jwtToken = requestTokenHeader.substring(7);

            try {

                username = jwtTokenUtil.getUsernameFromToken(jwtToken);

            } catch (IllegalArgumentException e) {

                System.out.println("Unable to get JWT Token");

            } catch (ExpiredJwtException e) {

                System.out.println("JWT Token has expired");

            }

        }
        else if (requestTokenHeader == null){

            logger.info("Does not provide Authorization Header");

        }
        else if (!requestTokenHeader.startsWith("Bearer ")){
            logger.warn("JWT Token does not begin with Bearer");
        }

// Once we get the token validate it.
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }
}

最后是 JwtAuthenticationEntryPoint:

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
    private static final long serialVersionUID = -7858869558953243875L;
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }
}

这是显示我没有在 header 中发送任何令牌的日志,但它允许请求: 在此处输入图像描述

知道我该怎么做吗? 有关更多信息,我应该说这段代码正在工作,但一段时间后停止工作,我没有找到任何原因,因为几个月来我没有对这些文件进行任何更改。

问题是这一行的错误配置

web.ignoring().mvcMatchers(String.valueOf(HttpMethod.OPTIONS), "/**");

它应该是

web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**");

您现在可能已经注意到,您的配置实际上忽略了来自 Spring 安全过滤器的所有请求路径。 这就是现在允许所有未经授权的请求(您期望的)的原因。

您缺少addFilterAfter并如下更新您的代码。

  @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.csrf().disable()

            .authorizeRequests().antMatchers("/authenticate","/user","/swagger-ui.html","/swagger-ui/**"
            ,"/v3/api-docs/**").permitAll().

            anyRequest().authenticated().and().

            exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()

            .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

   .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class).logout().logoutSuccessUrl("/authenticate").logoutUrl("/logout").permitAll();
}

请参考https://github.com/techiesantosh/taskmanager-service/blob/develop/src/main/java/com/web/taskmanager/config/TaskConfig.java

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM