簡體   English   中英

嘗試訪問不安全的路由時出現 Gettig 錯誤

[英]Gettig error while trying to access unsecured route

我在我的 java 項目中使用 spring 安全來保護 web 服務。 我所有的 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();
}
    

現在我需要創建一個每個人都可以訪問的 web 服務。 為此,我添加了這一行:

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

對於鏈式文件管理器,它看起來像這樣:

@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();
}

添加上面的行后,我得到異常 JWT not found,它來自這個由 addFilterAfter 觸發的 JwtTokenVerifier bean。

我的問題是,在請求不安全的 web 服務時,如何防止觸發 addFilterAfter 或僅安全路由所需的任何其他過濾器?

更新

這是 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;
    }
  }
}   

我知道你沒有問這個,但我首先建議你使用 Spring 安全的內置 JWT 支持而不是構建你自己的。 安全很難,使用經過審查的支持可能更安全。

關於為不同的端點使用單獨的身份驗證機制的問題,您可以改為發布兩個過濾器鏈,一個用於開放端點,一個用於基於令牌的端點,如下所示:

@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();
}

你有沒有試過這樣的事情:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM