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

Spring 403错误-尝试使用JWT令牌保护后端

吕衡
2023-03-14

我所有的请求都有403个被禁止的回复。我发送的firebase令牌正在成功验证,所以我不确定设置时缺少了什么步骤?我只是想让一个简单的流工作,其中我的endpoint必须在头中有有效的firebase JWT令牌(在排除的健康endpoint之外)。

当前步骤:

  1. 自定义OncePerRequest estFilter已创建并正在相应的endpoint上命中
  2. 授权头令牌成功验证
  3. 身份验证对象创建为UsernamePasswordAuthentiationToken,跟踪其中的Firebase令牌和用户UID。
  4. 使用新的身份验证对象设置SecurityContext。
  5. ???

响应:{"时间戳":"2022-01-09T16:44:08.342 00:00","状态": 403,"错误":"禁止","消息":"拒绝访问","路径":"/v1/dev/超重/服务/用户/注册"}

从身份验证中排除的我的健康endpoint也能够成功地进行调用。

@EnableWebSecurity
@Configuration
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

    @Value("${server.servlet.context-path:''}")
    private String contextPath;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors().and()
                .csrf().disable()
                .addFilterBefore(new FireBaseFilter(), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers("/health/**").permitAll()
                .anyRequest().authenticated();

    }

    @Override //src: https://www.baeldung.com/spring-cors
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins(
                "http://localhost:8080",
                "http://localhost:3000"
        ).allowedMethods("*");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
 @Slf4j
 public class FireBaseFilter extends OncePerRequestFilter {

    private List<String> skipUrls = Arrays.asList("/health/**");
    private static final String AUTH_HEADER = "Authorization";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authToken = request.getHeader(AUTH_HEADER).substring(7);
        if (!StringUtils.isEmpty(authToken)) {
            Authentication auth = getAuthentication(authToken);
            SecurityContextHolder.getContext().setAuthentication(auth);
        }

        filterChain.doFilter(request, response);
    }

    private Authentication getAuthentication(String jwtToken) {
        FirebaseToken token = verifyFireBaseToken(jwtToken);
        return new UsernamePasswordAuthenticationToken(token.getUid(), token);
    }

  private FirebaseToken verifyFireBaseToken(String jwtToken) {
        if (StringUtils.isEmpty(jwtToken)) {
            throw new IllegalArgumentException("idToken is blank");
        }
        try {
            return FirebaseAuth.getInstance().verifyIdToken(jwtToken, true);
        } catch (FirebaseAuthException e) {
            this.logger.error("exception thrown verifying firebase token");
        }
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return skipUrls.stream().anyMatch(p -> new AntPathMatcher().match(p, request.getServletPath()));
    }

}

共有1个答案

齐俊达
2023-03-14

@dur在评论中解决。我需要为UsernamePasswordAuthenticationToken(token.getUid(),token,)添加一些权限;

我将我的方法修改为:

private Authentication getAuthentication(String jwtToken) {
    FirebaseToken token = verifyFireBaseToken(jwtToken);
    this.logger.info("Token verified!");
    List<GrantedAuthority> authoritiesList = new ArrayList<GrantedAuthority>();
    authoritiesList.add(new SimpleGrantedAuthority("ADMIN"));
    return new UsernamePasswordAuthenticationToken(token.getUid(), token, authoritiesList);
}

我认为从这里开始,接下来的步骤将是创建一个适当的UserDetailsService来正确处理此问题。

 类似资料:
  • 我读到,当使用JWT时,不需要防止CSRF攻击,例如:“由于您不依赖cookie,您不需要防止跨站点请求”。 但是,有一点我不明白:如果我将令牌存储在localStorage中(正如我在同一网站的教程中被告知的那样),那么攻击者如何防止通过读取我的localStorage而不是Cookie来伪造恶意请求呢? 由于它是在服务器端生成的,我不知道如何在客户机请求中使用令牌而不将其存储在客户机的某个地方

  • 问题内容: 该问题在某种程度上与以下链接的问题有关。但是,我需要在某些方面和一些其他信息上多一点清晰度。 我需要使用令牌为REST Web服务实现安全性 该Web服务旨在与Java客户端一起使用。因此,表单身份验证和凭据弹出窗口没有用。 我是REST安全和加密的新手 这是我到目前为止所了解的: 对于第一个请求: 用户建立https连接(或容器使用301确保https) 用户POST输入用户名和密码

  • 我们有一个简单的应用程序,只有两个消费者和5个endpoint。对于一个endpoint,我需要某种身份验证方式。我喜欢这样做的条纹方式,但我不知道我如何可以在spring Boot中构建这个。 “对API的身份验证是通过HTTP基本身份验证执行的。请提供API密钥作为基本身份验证用户名值。不需要提供密码。”

  • 我的问题是,对每个表单使用一个令牌,而不更新每个表单提交的令牌,安全吗?这能防止CSRF吗?

  • 这个问题在某种程度上与下面的链接问题有关。然而,我需要在某些方面更多的澄清和一些额外的信息。参考:REST Web服务身份验证令牌实现 背景: null null 对于后续请求: 客户端发送此加密令牌和哈希组合(使用基本的用户名字段?) 我们使用哈希确保加密的令牌没有被篡改,然后对其解密 我们检查会话跟踪表中解密的令牌是否有未过期的条目,并获得实际的用户名(过期由代码管理?) 如果找到用户名,则根

  • 我正在使用JWTs为我的应用程序验证用户身份。当用户登录时,他们将获得一个访问令牌和一个刷新令牌。为了保证刷新令牌的安全,我不将其存储在客户端,而是将其与他们的帐户一起保存在后端,这样就不容易访问了。虽然我对刷新令牌的安全性感到困惑,但当我阅读关于如何使用刷新令牌的在线资源时,以下是我理解的逻辑: 身份验证 将访问令牌+刷新令牌存储在某个位置(在我的示例中,访问令牌位于前端,刷新令牌位于后端) 执