我正在使用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();
}
}
1条答案
按热度按时间hc8w905p1#
在你的
FirebaseAuthenticationFilter
中,如果没有Authorization
头,你可以让FilterChain
继续它的处理:这不应该是个问题,因为您配置了
AuthorizationFilter
(authorizeHttpRequests()
)以允许访问/api/v1/habit/**
,并要求对每个其他路径进行身份验证。