当前位置: 首页 > 知识库问答 >
问题:

自定义异常在使用spring boot和spring security的筛选器中不起作用

慎志国
2023-03-14

我正在使用Spring启动和Spring安全创建带有JWT令牌基础安全性的rest API。当令牌无效时,我想抛出自定义异常。因此,我创建了自定义异常类,每当我抛出该异常时,我每次都会在邮递员中收到空白响应。

我要扔这个

 if (header == null || !header.startsWith("Bearer")) {
    throw new JwtTokenMissingException("No JWT token found in the request headers");
  }

因为我发送的令牌没有承载关键字。它在控制台中打印,但不包括邮递员。

邮递员每次都有空白回复

JwtAuthenticationEntryPoint类

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable[!
    private static final long serialVersionUID = 1L;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }
}

WebSecurityConfig类

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

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

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

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }

    @Bean
    public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationFilter();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().antMatchers("/login").permitAll().anyRequest()
                .authenticated().and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public BCryptPasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

}
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwtTokenPrefix}")
    private String tokenPrefix;

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        String header = req.getHeader("Authorization");
        String username = null;
        String authToken = null;

        if (header == null || !header.startsWith("Bearer")) {
            throw new JwtTokenMissingException("No JWT token found in the request headers");
        }

        authToken = header.replace(tokenPrefix, "");
        jwtTokenUtil.validateJwtToken(authToken);
        username = jwtTokenUtil.getUserNameFromJwtToken(authToken);
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
                    null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
            logger.info("authenticated user " + username + ", setting security context");
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(req, res);
    }
}
@Component
public class JwtTokenUtil implements Serializable {

    private static final long serialVersionUID = 1L;

    @Value("${jwtSecret}")
    private String jwtSecret;

    @Value("${jwtExpirationInMs}")
    private int jwtExpirationMs;

    public String generateJwtToken(String username) {

        return Jwts.builder()
                .setSubject((username))
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }

    public String getUserNameFromJwtToken(String token) {
        return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
    }

    public void validateJwtToken(String authToken) throws JwtTokenMalformedException, JwtTokenMissingException {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
        } catch (SignatureException e) {
            throw new JwtTokenMalformedException("Invalid JWT signature");
        } catch (MalformedJwtException e) {
            throw new JwtTokenMalformedException("Invalid JWT token");
        } catch (ExpiredJwtException e) {
            throw new JwtTokenMalformedException("Expired JWT token");
        } catch (UnsupportedJwtException e) {
            throw new JwtTokenMalformedException("Unsupported JWT token");
        } catch (IllegalArgumentException e) {
            throw new JwtTokenMissingException("JWT claims string is empty.");
        }
    }

}
public class JwtTokenMalformedException extends AuthenticationException {
    private static final long serialVersionUID = 1L;

    public JwtTokenMalformedException(String msg) {
        super(msg);
    }
}


public class JwtTokenMissingException extends AuthenticationException {
    private static final long serialVersionUID = 1L;

    public JwtTokenMissingException(String msg) {
        super(msg);
    }
}

共有1个答案

万俟震博
2023-03-14

试试下面的代码:

String jwtToken = null;

if(headers.containKey("Authorization")){
   jwtToken = headers.get("Authorization");
}

if (jwtToken == null || !jwtToken.startsWith("Bearer")) {
    throw new JwtTokenMissingException("No JWT token found in the request headers");
}
 类似资料:
  • 我创建了一个自定义异常类 并且在抛出异常时将此异常类发送到客户端。我还使用进行进程。 如何捕获安全过滤器抛出异常并创建用户定义的异常并将其发送到客户端? 我的过滤方法,

  • 存储在Django模型中的元素如下 示例数据如下: . 结果:找到对象- 结果:找到对象- 结果:找到对象- 结果:未找到对象 如何使用过滤器和正则表达式进行这些查询?

  • 我试图查询存在特定字段的日期范围。这似乎很容易,但我感觉到关键字“exists”在文档中发生了变化。我在5.4。https://www.elastic.co/guide/en/elasticsearch/reference/5.4/query-dsl-exists-filter.html 我使用@timestamp表示日期,并且字段“error_data”在映射中,只有在发现错误条件时才出现。 以

  • 我试图在map()中使用filter(),但我得到了这个火花异常: RDD转换和操作只能由驱动程序调用,不能在其他转换内部调用;例如,rdd1。地图(x)= 我知道火花不允许嵌套转换/动作/RDD,所以有人可以给我一个建议,如何替代它(没有嵌套转换或动作),我有一个RDD它的元组是这样的: 我试着映射它,给它一个列表作为参数,这个列表包含javaPairRDD这样的: 这些行指的是修改RDD()函

  • 下面是过滤器的外观。 对于WebSecurityConfigurerAdapter#configure(webSecurityWeb)web.忽略()中包含的路径,我希望该筛选器不会像Spring Security筛选器链的其余部分一样激发。 下面是它的样子 我希望在调用Spring Security链的其余部分时调用这个过滤器,并对web.igneration()中的路径忽略这个过滤器,就像Sp

  • 我在Angular中有一个自定义验证的表单构建器,但我在自定义验证中读取文件后无法获取文件的类型。 下面是StackBlitz: https://stackblitz.com/edit/Angular-ivy-atwqqc?file=src%2fapp%2fapp.component.ts TS文件