为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Spring Security 为基本身份验证和 JWT 配置多种身份验证类型

使用 Spring Security 为基本身份验证和 JWT 配置多种身份验证类型

慕村225694 2023-08-23 14:32:52
我有一个 API,需要通过两种不同的方式来保护:1) 对除 1 之外的所有请求 URL 使用 JWT,这些请求 URL 需要通过基本身份验证进行保护2) 一个 url 的基本身份验证。我已经为 JWT 和基本身份验证设置了安全配置。我的问题是,当我使用有效的用户名和密码向基本身份验证 URL 发出请求时,它成功地对我进行了身份验证,并完成了在 cassandra 中存储数据的工作。然后,我希望必须通过 /api/login 为所有其他请求 URL 生成令牌,并将其添加到 Authorization: Bearer {Token} 标头中。但是,如果我通过基本身份验证进行了身份验证,则我可以访问其他 URL(受 JWT 身份验证保护),甚至无需在请求中包含令牌。当我在没有使用基本身份验证的情况下访问受 JWT 保护的 URL 时,我必须在标头中发送令牌,并且它会按预期工作。我应该期待这个吗?我相信,即使我通过一个端点的基本身份验证进行了身份验证,我仍然应该在所有其他受保护的 JWT 端点的请求中发送令牌。我找到了这个答案: SpringBoot multipleauthenticationadapter还有这篇文章: https://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/#multiple-httpsecurity并尝试实施解决方案,但所解释的问题仍然出现。使用 BasicAuthEntryPoint 类:public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {    private static final Gson gson = new Gson();    @Override    public void commence(final HttpServletRequest request, final HttpServletResponse response,            final AuthenticationException authException) throws IOException, ServletException {        // Authentication failed, send error response.        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);        PrintWriter writer = response.getWriter();        writer.println(gson.toJson("HTTP Status 401 : " + authException.getMessage()));    }    @Override    public void afterPropertiesSet() throws Exception {        setRealmName("Realm");        super.afterPropertiesSet();    }还有 JWT impl:@Componentpublic class JwtAuthenticationTokenFilter extends OncePerRequestFilter {    @Value("${jwt.header}")    private String tokenHeader;我希望这是有道理的。如果还有其他问题,请告诉我,但似乎无法解决这个问题。我首先添加了“特殊情况”,这是基本身份验证的一个 url,但仍然没有任何区别。谢谢
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

您在安全配置中发布的代码@Order(1)


@Override

protected void configure(HttpSecurity http) throws Exception {

    http.csrf().disable().authorizeRequests().antMatchers("/v1/crash/consumeCrashBoxxEvent").hasRole("ADMIN").and()

            .httpBasic().authenticationEntryPoint(getBasicAuthEntryPoint()).and().sessionManagement()

            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

}

如果这正是您正在使用的代码,则@Order(2)不会咨询您的配置。这将是死配置。
让我解释!
http.authorizeRequests()==http.antMatcher("/**").authorizeRequests()

在你的第一个配置中,你使用了通配符,你的配置结果是

  • /v1/crash/consumeCrashBoxxEvent如果用户经过身份验证并且具有 ADMIN 角色,则可以访问

  • Rest of URL's如果用户通过身份验证则可以访问

让我猜猜发生了什么!
1. 您正在点击 URL /v1/crash/consumeCrashBoxxEvent,否则any URL系统将提示您进行基本身份验证。
2. 身份验证成功后,您可以访问任何 URL,因为您是经过身份验证的用户。

但是,如果我通过基本身份验证进行了身份验证,则我可以访问其他 URL(受 JWT 身份验证保护),甚至无需在请求中包含令牌。

因为正如我所说,您可以访问任何 URL,因为您是经过身份验证的用户

当我在没有使用基本身份验证的情况下访问受 JWT 保护的 URL 时,我必须在标头中发送令牌,并且它会按预期工作

检查没有令牌您是否可以访问。因为一旦您通过基本身份验证登录,就不会从服务器端注销(即使您重新启动服务器)。只有关闭浏览器才能实现注销。因此,您可以通过关闭并再次启动浏览器来测试它。并通过不发送 JWT 令牌来测试它。
还要确保您的请求到达 JwtAuthenticationTokenFilter,放入调试日志进行验证。

正如您的问题中有很多抽象,除非您发布完整的代码,否则很难准确预测正在发生的情况。

如果我的预测与实际有所偏差,请在评论中告诉我。



查看完整回答
反对 回复 2023-08-23
?
holdtom

TA贡献1805条经验 获得超10个赞

这是通过使用 Praveen Kumar Lalasangi 的上述答案中提供的信息解决的。


对方法的一个小改变configure就达到了目的。更新是:


@Override

    protected void configure(HttpSecurity http) throws Exception {

      http.csrf().disable()

      .antMatcher(crashBoxxConsumeEndpoint).authorizeRequests().anyRequest()

      .hasRole("ADMIN")

      .and().httpBasic().authenticationEntryPoint(getBasicAuthEntryPoint())

      .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }


查看完整回答
反对 回复 2023-08-23
  • 2 回答
  • 0 关注
  • 181 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信