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

带有permitAll()和过期Auth令牌的URL的Spring Security性

燕扬
2023-03-14
@Configuration
@ComponentScan(basePackages={"com.api.security"})
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private ApiAuthenticationProvider apiAuthenticationProvider;

@Autowired
private AuthTokenHeaderAuthenticationFilter authTokenHeaderAuthenticationFilter;

@Autowired
private AuthenticationEntryPoint apiAuthenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(apiAuthenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(authTokenHeaderAuthenticationFilter, BasicAuthenticationFilter.class) // Main auth filter
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()
        .anyRequest().authenticated();

    http.exceptionHandling()
        .authenticationEntryPoint(apiAuthenticationEntryPoint);
}
}
/**
 * Main Auth Filter. Always sets Security Context if the Auth token Header is not empty
 */
@Component
public class AuthTokenHeaderAuthenticationFilter extends GenericFilterBean {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    final String token = ((HttpServletRequest) request).getHeader(RequestHeaders.AUTH_TOKEN_HEADER);
    if (StringUtils.isEmpty(token)) {
        chain.doFilter(request, response);
        return;
    }

    try {
            AuthenticationToken authRequest = new AuthenticationToken(token);

              SecurityContextHolder.getContext().setAuthentication(authRequest);
        }
    } catch (AuthenticationException failed) {
        SecurityContextHolder.clearContext();

        return;
    }

    chain.doFilter(request, response); // continue down the chain
}

}

自定义apiAuthenticationProvider将尝试基于标头中提供的令牌对所有请求进行身份验证,如果身份验证不成功,则抛出AccessException,客户端将收到HTTP 401响应:

@Component
public class ApiAuthenticationProvider implements AuthenticationProvider {

@Autowired
private remoteAuthService remoteAuthService;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    AuthenticationToken authRequest = (AuthenticationToken) authentication;
    String identity = null;

    try {
        identity = remoteAuthService.getUserIdentityFromToken(authRequest.getToken());
    } catch (AccessException e) {
        throw new InvalidAuthTokenException("Cannot get user identity from the token", e);
    }

    return new AuthenticationToken(identity, authRequest.getToken(), getGrantedAuthorites());
    }
    }

这对于需要身份验证的请求非常有效。对于没有身份验证标头的/v2/session请求,这很好。但是,对于/v2/session请求,如果在头部(或在cookie中--代码示例中没有显示;如果客户机没有清除头部或继续发送带有请求的cookie,有时可能会发生这种情况)中有一个过期的Auth令牌,则安全上下文将被初始化,apiAuthenticationProvider将抛出一个异常,并用HTTP 401响应客户机。

http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()

我希望Spring Security性在调用apiauthenticationProvider.authenticate()之前确定这一点。对于配置为permitAll()的URL,过滤器或auth提供者应该如何忽略/不抛出异常?

共有1个答案

韦熙云
2023-03-14

在执行请求授权检查之前触发Spring Security过滤器。为了使授权检查发挥作用,假定请求已经通过过滤器,并且已经设置了Spring Security上下文(是否设置,取决于是否传入了身份验证凭据)。

在您的筛选器中,如果令牌不在,您可以检查是否继续进行筛选器链处理。不幸的是,如果它是,那么它将被传递给您的提供者进行身份验证,这将引发异常,因为令牌已经过期,因此您将获得401。

最好的办法是对您认为是公共的URL跳过筛选器执行。您既可以在筛选器本身中执行此操作,也可以在配置类中执行此操作。将以下方法添加到SecurityConfig类中:

@Override
public void configure(WebSecurity webSecurity) {
  webSecurity.ignoring().antMatchers(HttpMethod.POST, "/v2/session");
}
 类似资料:
  • 这个问题看起来可能重复,但以下答案都没有解释何时使用: 和 HttpSecurity、WebSecurity和AuthenticationManagerBuilder Spring Security中Web忽略和Http允许的区别 通过阅读StackOverflow asnwers和几篇文章,我了解到: configure(HttpSecurity)允许在资源级别配置基于web的安全性。 conf

  • 我试图使用资源令牌连接到Azure Cosmos DB中的Gremlin集合。我从这里修改了文档(主要针对C#):https://docs.microsoft.com/en-us/azure/cosmos-db/how-to-use-resource-tokens-gremlin 问题是,一旦我试图访问数据,令牌的日期标头似乎无效: 有人知道怎么解决吗?通过将JVM设置为GMT 连接并查询Grem

  • null 我目前拥有的是以下内容:当密码哈希和用户名在数据库中匹配时,刷新令牌endpoint生成一个JWT。每个刷新令牌都有一个存储在数据库中的jti,以及过期(仅用于DB清理)、device_id和一个revoked标志。可以使用refresh令牌命中另一个endpoint,该令牌返回一个JWT访问令牌。访问令牌的有效期为15分钟。无法吊销访问令牌。 我的问题出现在需求1上。我不希望用户在与网

  • 我有一个带有JWT auth的Spring boot应用程序,非常好用!但我用无状态策略禁用了csrf: 这个Rest应用编程接口是为SPA反应应用程序设计的。我读到当我使用JWT令牌时,我不需要设置csrf令牌。JWT是否像csrf保护一样工作?我认为这不是csrf保护。

  • 我试图做api-auth通过检查生成令牌从登录用户的用户名与md5加密方法在laravel 5.5飞,不想保存令牌到用户的表。当用户注销时,令牌将无效。URL将是这样的: http://myserver.com/products?token=...... 我该怎么做? 新增-这是第44届世界技能大赛的测试项目,以下为测试项目文件: 认证 A.登录(v1/auth/登录) 描述:供客户端通过用户名和

  • 本文件规定: Firebase ID令牌是短暂的,只能持续一个小时;刷新令牌可用于检索新的ID令牌。 我是否可以说,刷新令牌本质上同时充当客户端设备的密码和标识,并且拥有刷新令牌意味着能够检索ID令牌,从而能够作为与该刷新令牌关联的用户进行身份验证? 如果是这样,那么拥有这两个不同的令牌的目的是什么? 谢谢