简体   繁体   English

尝试访问不安全的路由时出现 Gettig 错误

[英]Gettig error while trying to access unsecured route

I am using spring security in my java project to secure web services.我在我的 java 项目中使用 spring 安全来保护 web 服务。 All my web services are secured here are filter chain configuiration that i use:我所有的 web 服务都在这里受到保护,是我使用的过滤器链配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .cors().and()
            .csrf().disable()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(new JwtEmailAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, secretKey))
            .addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig),JwtEmailAndPasswordAuthenticationFilter.class)
            .authorizeRequests()
            .anyRequest()
            .authenticated();
}
    

Now I have a requirement to create one web service that will be accessible to everybody.现在我需要创建一个每个人都可以访问的 web 服务。 For this purpose I add this row:为此,我添加了这一行:

.and().authorizeRequests().antMatchers("/auth/reset").permitAll()

To chained filers and it looks like that:对于链式文件管理器,它看起来像这样:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .cors().and()
            .csrf().disable()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(new JwtEmailAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, secretKey))
            .addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig),JwtEmailAndPasswordAuthenticationFilter.class)
            .authorizeRequests()
            .and().authorizeRequests().antMatchers("/auth/reset").permitAll()
            .anyRequest()
            .authenticated();
}

After adding the row above I get exception JWT not found, it comes from this JwtTokenVerifier bean which is fired by addFilterAfter.添加上面的行后,我得到异常 JWT not found,它来自这个由 addFilterAfter 触发的 JwtTokenVerifier bean。

My question is how can I prevent trigger addFilterAfter or any other filter that is needed only for the secured routes in case of the request for an unsecured web service?我的问题是,在请求不安全的 web 服务时,如何防止触发 addFilterAfter 或仅安全路由所需的任何其他过滤器?

UPDATE更新

Here is definition of JwtTokenVerifier bean:这是 JwtTokenVerifier bean 的定义:

public class JwtTokenVerifier extends OncePerRequestFilter {
    private final SecretKey secretKey;
    private final JwtConfig jwtConfig;

    public JwtTokenVerifier(SecretKey secretKey,
                            JwtConfig jwtConfig) {
        this.secretKey = secretKey;
        this.jwtConfig = jwtConfig;
    }

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

        try {
            
            String authorizationHeader = request.getHeader(jwtConfig.getAuthorizationHeader());

            if (Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith(jwtConfig.getTokenPrefix())) {
                filterChain.doFilter(request, response);
                return;
            }

            String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), "");

            try {

                Jws<Claims> claimsJws = Jwts.parser()
                        .setSigningKey(secretKey)
                        .parseClaimsJws(token);

                Claims body = claimsJws.getBody();

                String email = body.getSubject();

                var authorities = (List<Map<String, String>>) body.get("authorities");

                Set<SimpleGrantedAuthority> simpleGrantedAuthorities = authorities.stream()
                        .map(m -> new SimpleGrantedAuthority(m.get("authority")))
                        .collect(Collectors.toSet());

                Authentication authentication = new UsernamePasswordAuthenticationToken(
                        email,
                        null,
                        simpleGrantedAuthorities
                );

                SecurityContextHolder.getContext().setAuthentication(authentication);

            } catch (JwtException e) {
                throw new IllegalStateException(String.format("Token %s cannot be trusted", token));
            }

            filterChain.doFilter(request, response);
        } catch (JwtException e) {
        throw e;
    }
  }
}   

I realize you didn't ask this, but I'd first recommend that you use Spring Security's built-in JWT support instead of building your own.我知道你没有问这个,但我首先建议你使用 Spring 安全的内置 JWT 支持而不是构建你自己的。 Security is hard, and using vetted support is likely more secure.安全很难,使用经过审查的支持可能更安全。

Regarding your question about having separate auth mechanisms for separate endpoints, you can instead publish two filter chains, one for open endpoints and one for token-based endpoints like so:关于为不同的端点使用单独的身份验证机制的问题,您可以改为发布两个过滤器链,一个用于开放端点,一个用于基于令牌的端点,如下所示:

@Bean
@Order(0)
SecurityFilterChain open(HttpSecurity http) {
    http
        .requestMatchers((requests) -> requests.antMatchers("/auth/reset"))
        .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll());

    return http.build();
}

@Bean
SecurityFilterChain tokenBased(HttpSecurity http) {
    http
        .authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
        .addFilter(...)
        .addFilterAfter(...);

    return http.build();
}

Have you tried something like that:你有没有试过这样的事情:

 .and().authorizeRequests().antMatchers("...").permitAll().and().addFilter(...).authorizeRequests().anyRequest().authenticated().and()

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

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