Spring Boot Security - 如果缺少授权标头,则使用 Cookie 中的令牌

the*_*ish 8 java spring spring-security jwt spring-boot

我目前根据授权服务器的 JWK 验证我的请求。我spring-boot-starter-oauth2-resource-server在 spring-boot 2.3 上使用该包。JWT 从标头中取出Authorization: Bearer <token>并针对 JWK 端点进行验证。我的安全配置如下所示:

安全配置.java

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  protected Environment env;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeRequests().antMatchers("/logs").permitAll();
    http.authorizeRequests().antMatchers("/", "/api/**").authenticated();
    http.oauth2ResourceServer().jwt();
  }
}
Run Code Online (Sandbox Code Playgroud)

应用程序属性

spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://auth.work.com/v1/jwk
Run Code Online (Sandbox Code Playgroud)

外部用户的请求中没有Authorization: ...标头,而是具有以下 2 个构成 JWT 的 cookie:

auth.token_type = Bearer
auth.access_token = <token>
Run Code Online (Sandbox Code Playgroud)

有没有办法从 cookie 中提取 JWT 并在标头Authorization: ...丢失时针对身份验证服务器进行验证?我可以在尝试授权之前提取 cookie 并向请求添加标头吗?或者它甚至可能是身份验证链中的第二种方法。

the*_*ish 15

我发现了自定义令牌解析器,并最终创建了一个来验证标头和 cookie。我不确定这是否是最干净的解决方案,但它确实有效。

我遇到的唯一问题是它不再自动验证标Authorization: Bearer ...头,因此我也必须为其添加代码。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeRequests().antMatchers("/logs").permitAll();
    http.authorizeRequests().antMatchers("/", "/api/**").authenticated();
    http.oauth2ResourceServer().jwt().and().bearerTokenResolver(this::tokenExtractor);
  }

  public String tokenExtractor(HttpServletRequest request) {
    String header = request.getHeader(HttpHeaders.AUTHORIZATION);
    if (header != null)
      return header.replace("Bearer ", "");
    Cookie cookie = WebUtils.getCookie(request, "auth.access_token");
    if (cookie != null)
      return cookie.getValue();
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 2

只需创建一个@Component实现该BearerTokenResolver接口的带注释的类:

@Override
public String resolve(final HttpServletRequest request) {
    Cookie cookie = WebUtils.getCookie(request, "YOUR_COOKIE_NAME");
    if (cookie != null)
        return cookie.getValue();
    else
        return new DefaultBearerTokenResolver().resolve(request);
}
Run Code Online (Sandbox Code Playgroud)

这样,Spring 将不会创建默认DefaultBearerTokenResolver实现的实例,如果需要,您仍然可以在重写的resolve方法中重用该实例,以从标头中检索令牌。

问候。