特定用户组应该可以访问不同的 API 路由。例如,鉴于以下HttpSecurity
我们允许CUSTOMER
访问GET /invoices/*
。另外,我想允许ADMIN
访问任何路由/**
。
@Override
protected void configure(HttpSecurity http) throws Exception {
http = http
.cors().and()
.csrf().disable(); // REST only
// ### Authentication
// ...
// ### Authorization
// anonymous (and all other roles)
e = e
.antMatchers(HttpMethod.POST,
"/user/account/create",
"/user/account/confirm/*",
"/feedback")
.permitAll()
.antMatchers(HttpMethod.GET,
"/" + StorageController.STORAGE_RELATIVE_PATH, // public files
"/translations/*")
.permitAll();
// role CUSTOMER
e = e
.antMatchers(HttpMethod.GET,
"/invoices",
"/invoices/*")
.hasRole(Role.CUSTOMER.toString())
.antMatchers(HttpMethod.PUT,
"/profile",
"/contracts/billingAddress")
.hasRole(Role.CUSTOMER.toString())
.antMatchers(HttpMethod.POST,
"/contracts",
"/profile/logo")
.hasRole(Role.CUSTOMER.toString());
// only ADMIN
e = e.antMatchers("/**").hasRole(Role.ADMIN.toString());
}
虽然允许ADMIN
使用所有未提及的/admin/.../
路由,但该角色403
,例如,/invoices/*
- 为什么?据我了解,指定的配置取决于顺序,因此需要/invoices/*
具有CUSTOMER
角色,因此ADMIN
是不够的 - 对吗?
如果我添加以下内容(第CUSTOMER or ADMIN
节(,它可以工作,但总是列出ADMIN
角色非常麻烦。我只是希望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());
}
此外,我不能将ADMIN
规则置于其他规则之上,因为它会排除其他角色访问任何内容。有没有办法以更优雅/更简单的方式指定我想做什么?
正如您在问题中指出的,发生此行为是因为每个匹配器都按照声明的顺序进行考虑。
对/invoices
的请求将首先到达以下匹配器,由于它是匹配项,因此它将应用关联的规则。
.antMatchers("/invoices").hasRole("CUSTOMER")
如果发出请求的用户只有角色"ADMIN"
则他们将被拒绝访问,因为"ADMIN"
不是"CUSTOMER"
。
选项 1
若要获取所需的行为,可以显式列出有权访问终结点的角色。
正如您提到的,这很冗长,但是,优点是它清楚地指示了一个地方允许的角色。
.antMatchers("/invoices").hasAnyRole("CUSTOMER", "ADMIN")
选项 2
如果"ADMIN"
应该能够执行"CUSTOMER"
可以执行的任何操作,则可以声明一个RoleHierarchy
,声明任何"ADMIN"
也是"CUSTOMER"
。
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_CUSTOMER");
return hierarchy;
}
>
符号可以被认为是"包括"的意思。
然后,任何受.hasRole("CUSTOMER")
保护的端点也可以由具有角色"ADMIN"
的用户访问,因为具有角色"ADMIN"
意味着它们也具有角色"CUSTOMER"
。