Spring Boot 使用Firebaes身份验证的Java Sping Boot Security的白色名单URL

dkqlctbz  于 2023-03-23  发布在  Spring
关注(0)|答案(1)|浏览(188)

我正在使用Java Sping Boot 构建一个简单的API。这将执行基本的CRUD操作。我希望一些路径经过身份验证,而一些路径不经过身份验证。在本例中,我希望将/habit/my路径列入白色名单,而所有其他路径都是安全的。我正在使用的其他安全路径之一是/user
我遇到的问题是在当前的实现中。所有的请求,包括白色名单,一旦命中过滤器,并说它需要进行身份验证。我真的不知道我做错了什么。我真的需要一些帮助,了解我可能会出错的地方。非常新的Java和Sping Boot 工作。
在这里我分享了AuthenticationFilter,Auth Provider,Model(用于存储经过身份验证的用户)和安全配置。
身份验证筛选器

public class FirebaseAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final String AUTH_HEADER = "Authorization";

    public FirebaseAuthenticationFilter() {
        super(request -> true);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        final String token = request.getHeader(AUTH_HEADER);
        if(token == null) {
            throw new IllegalArgumentException("No Auth Token in header - " + AUTH_HEADER);
        }
        try {
            FirebaseToken firebaseToken = FirebaseAuth.getInstance().verifyIdToken(token);
            AbstractAuthenticationToken authenticationToken = new FirebaseAuthenticationToken(firebaseToken);
            return getAuthenticationManager().authenticate(authenticationToken);
        }
        catch (FirebaseException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // This updates the SecurityContextHolder
        super.successfulAuthentication(request, response, chain, authResult);
        chain.doFilter(request,response);
    }
}

身份验证提供程序

@Component
public class FirebaseAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        FirebaseAuthenticationToken firebaseAuthenticationToken = (FirebaseAuthenticationToken) authentication;
        firebaseAuthenticationToken.setAuthenticated(true);
        return firebaseAuthenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return FirebaseAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

AuthenticationToken(型号)

public class FirebaseAuthenticationToken extends AbstractAuthenticationToken {

    private final FirebaseToken firebaseToken;

    public FirebaseAuthenticationToken(FirebaseToken firebaseToken)  {
        super(null);
        this.firebaseToken = firebaseToken;
        setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return firebaseToken;
    }

    public String getEmail() {
        return firebaseToken.getEmail();
    }

    public String getAuthUid() {
        return firebaseToken.getUid();
    }

    @Override
    public Object getPrincipal() {
        return firebaseToken.getClaims();
    }

    @Override
    public boolean implies(Subject subject) {
        return super.implies(subject);
    }
}

安全配置

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    final private FirebaseAuthenticationProvider firebaseAuthenticationProvider;
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        FirebaseAuthenticationFilter filter = new FirebaseAuthenticationFilter();
        //AuthenticationManager is responsible for invoking the authentication provider(s) to authenticate the user.
        filter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));

        http
                .csrf().disable()
                .authenticationProvider(firebaseAuthenticationProvider)
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/api/v1/habit/**").permitAll()
                        .anyRequest().authenticated()
                )
                .addFilterAt(filter, BasicAuthenticationFilter.class);
        return http.build();
    }
}
hc8w905p

hc8w905p1#

在你的FirebaseAuthenticationFilter中,如果没有Authorization头,你可以让FilterChain继续它的处理:

final String token = request.getHeader(AUTH_HEADER);
if(token == null) {
    return null;
}

这不应该是个问题,因为您配置了AuthorizationFilterauthorizeHttpRequests())以允许访问/api/v1/habit/**,并要求对每个其他路径进行身份验证。

相关问题