Spring boot antMatchers允许管理所有路由,同时限制其他角色

Spring boot antMatchers允许管理所有路由,同时限制其他角色,spring-boot,spring-security,Spring Boot,Spring Security,特定用户组应该可以访问不同的api路由。例如,考虑到以下HttpSecurity,我们允许客户访问GET/invoices/*。另外,我想允许管理员访问任何路由/** 虽然允许管理员使用所有未提及的/ADMIN/../routes,但角色get的作用是403,例如,/invoices/*-为什么?据我所知,指定的配置取决于订单,因此要求/invoices/*具有客户角色,因此ADMIN不够-正确吗 如果我添加下面的“客户”或“管理员”部分,它会起作用,但总是列出管理员角色太麻烦了。我只是希望管理

特定用户组应该可以访问不同的api路由。例如,考虑到以下HttpSecurity,我们允许客户访问GET/invoices/*。另外,我想允许管理员访问任何路由/**

虽然允许管理员使用所有未提及的/ADMIN/../routes,但角色get的作用是403,例如,/invoices/*-为什么?据我所知,指定的配置取决于订单,因此要求/invoices/*具有客户角色,因此ADMIN不够-正确吗

如果我添加下面的“客户”或“管理员”部分,它会起作用,但总是列出管理员角色太麻烦了。我只是希望管理员能够访问所有内容

@Override
protected void configure(HttpSecurity http) throws Exception {
    // ...
    // role CUSTOMER
    e = e
            // ... as above ...


    // CUSTOMER or ADMIN
    e = e
            .antMatchers(HttpMethod.GET,
                    "/invoices/*") // AGAIN
            .hasAnyRole(Role.CUSTOMER.toString(),
                    Role.ADMIN.toString());

    // only ADMIN
    e = e.antMatchers("/**").hasRole(Role.ADMIN.toString());
}

此外,我不能将管理规则置于其他规则之上,因为它将排除其他角色访问任何内容。是否有一种方法可以以更优雅/更简单的方式指定我想要做什么?

正如您在问题中所指出的,出现这种行为是因为每个匹配器都是按其声明的顺序考虑的

对/发票的请求将首先到达下面的匹配者,因为它是匹配项,所以将应用关联规则

.antMatchers("/invoices").hasRole("CUSTOMER")
如果发出请求的用户只有ADMIN角色,那么他们将被拒绝访问,因为ADMIN不是客户

选择1

要获得所需的行为,您可以显式列出有权访问端点的角色

正如您所提到的,这是冗长的,但是,其优点是它在一个位置清楚地指示了允许的角色

.antMatchers("/invoices").hasAnyRole("CUSTOMER", "ADMIN")
选择2

如果管理员应该能够做客户可以做的任何事情,那么您可以声明一个角色层次结构,声明任何管理员也是客户

>符号可以被视为包含含义


然后,任何受.hasRoleCUSTOMER保护的端点也可以由角色ADMIN的用户访问,因为拥有角色ADMIN意味着他们也拥有角色CUSTOMER。

基本上,我想告诉一个角色,然后列出所有允许的路由;但相反,我觉得必须列出这些路线,并为每个路线说明哪些角色可以访问它们。最后,我觉得给出的方法是一个糟糕的设计。或者我们应该决定将路由按语义分组到端点,例如all/invoices/**路由,告诉哪个角色可以访问哪个特定路由,或者按角色分组,告诉他们可以访问哪些路由,但我觉得这不受支持?!。但给定的方法是一团乱,试图最小化配置代码。但是,它不容易维护。您是否尝试反转e.antMatchers/**.hasRoleRole.ADMIN.toString;成为第一个出现的匹配者?你说的反转是什么意思?只需将规则放在第一位,所有其他角色都将得到403。
.antMatchers("/invoices").hasAnyRole("CUSTOMER", "ADMIN")
@Bean
public RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
    hierarchy.setHierarchy("ROLE_ADMIN > ROLE_CUSTOMER");
    return hierarchy;
}