如何根据http标头过滤JWT身份验证权限

时间:2019-02-21 16:06:24

标签: java spring-boot spring-security jwt

基本上,我想在解析JWT令牌之后并且在调用该方法之前具有基于http标头修改身份验证对象的能力来实现过滤器

上下文

在我们的应用程序中,我们(除其他外)具有三个与身份验证/授权相关的实体:用户,权限和组。权限可以直接分配给用户,也可以分配给用户所属的组之一。

鉴于此,JWT令牌如下所示:

{
  "username": "duck",
  "groups": [
    {
      "name": "swimmer",
      "permissions": [
        "swim"
      ]
    },
    {
      "name": "walker",
      "permissions": [
        "walk"
      ]
    }
  ],
  "permissions": [
    "quack"
  ]
}

JWT流设置为扩展AuthorizationServerConfigurerAdapterResourceServerConfigurerAdapter,并通过扩展DefaultUserAuthenticationConverter从JWT声明映射中提取权限

通过在配置中使用@EnableGlobalMethodSecurity(prePostEnabled = true),我可以使用@PreAuthorize注释方法

例如:

@PreAuthorize("hasPermission('quack')")
public void quack();

这适用于直接分配给用户的权限。

但是我想接收一个http标头,例如:“ x-group”,并将该组(如果有)的权限添加到身份验证对象

然后,给定上面的'jwt',并将http标头设置为swimmer,我希望能够调用以下方法:

@PreAuthorize("hasPermission('swim')")
public void 

1 个答案:

答案 0 :(得分:0)

我知道您没有问这个问题,但是除非您信任其来源(例如,已签名或类似内容),否则从标题中建立其他权限听起来有点冒险。听起来很奇怪,因为使用OAuth的原因通常是因为授权服务器只是颁发颁发机构。

由于您已经在使用DefaultUserAuthenticationConverter,所以我想知道您是否能够从后端获得相同的额外权限,例如通过UserDetailsService的实例?

也就是说,要回答您的问题,您可以添加一个过滤器:

public class XGroupFilter extends OncePerRequestFilter {
    // ... look up current Authentication
    // ... look up and validate header
    // ... create new instance of Authentication, adding the new authorities
}

然后注册:

@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) {
        // ...

        http.addFilterAfter(new XGroupFilter(), OAuth2AuthenticationProcessingFilter.class);
    }
}

或者,如果您可以选择升级,则可以使用new support as of Spring Security 5.1进行简化。您现在使用的是一个名为Spring Security OAuth的旧插件项目,但现在支持built in natively。此外,如果您还不走Spring Security OAuth的道路,那就是新功能的去向,这使从那里开始有价值。

在这种情况下,配置仍然非常相似:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) {
        // ...

        http.addFilterAfter(new XGroupFilter(), BearerTokenAuthenticationFilter.class);
    }
}