我需要某种@preFilter
(或者,如果不可能超过@postFilter
(来过滤我的REST API的结果。我不能使用preFilter
注释,因为我需要考虑用户角色。我有三个不同的角色:
-
user
普通用户,他们应该只访问他拥有的数据 -
teamleader
此角色应访问其团队的所有数据 -
admin
谁可以访问所有数据。
因为我们的数据库结构非常复杂,所以在我决定用户是否可以访问请求的数据或部分请求数据之前,有必要访问一些其他数据。
该代码段仅适用于角色user
和admin
。对于组长来说,它会更复杂,然后会有一堆masterDataId
必须与or
连接。
这里有一些伪代码,希望它不会混淆:
public class RoleFilter {
DimensionAttributeValueRepository dimensionAttributeValueRepository;
public void doFilter(Collection<AllDatas> data) {
if (user.getRole() != "admin") {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
DimensionAttributeValue tmpValue = dimensionAttributeValueRepository.findByChrValue(auth.getUsername());
MasterData masterData = tmpValue.getMasterData();
data.filter(data.masterDataId == masterData.getMasterDataID());
}
}
}
更新:示例
假设我有两个用户,用户 A 是角色为"用户"的普通用户。用户 B 是具有"管理员"角色的管理员。
有一个数据库表,其中存储userData
。该表如下所示。
| ID | username | name | email |
他们都在向/userData
发送一个简单的经过身份验证的GET
请求。
现在,我的后端根据authentication
标头检测用户并添加角色。
Nwo 根据角色的不同,用户 A 应该只获得包含其个人数据的 ansare,用户 B 应该获取通过/userData
可以访问的所有数据。
对用户 A 的响应:
{
"res":[
{
"id":1,
"username":"userA",
"name":"A",
"email":"userA@mail.com"
}
]
}
对用户 B 的响应:
{
"res":[
{
"id":1,
"username":"userA",
"name":"A",
"email":"userA@mail.com"
},
{
"id":2,
"username":"userB",
"name":"B",
"email":"userB@mail.com"
},
{
"id":3,
"username":"userC",
"name":"C",
"email":"userC@mail.com"
}
]
}
对于您的用例,我建议使用自定义过滤器并将其集成到spring-security
过滤器链中。这是一个教程,一般解释它。您可以配置自定义筛选器,以便它根据数据库检查您的复杂角色,然后用新对象覆盖当前用户身份验证对象。
实现示例:
public class CustomFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// HERE GOES YOUR CODE
// Depending on the extracted authentication details of the current user, you can now overwrite the users GrantedAuthorities
Collection<SimpleGrantedAuthority> oldAuthorities = (Collection<SimpleGrantedAuthority>)SecurityContextHolder.getContext().getAuthentication().getAuthorities();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_TEAMLEADER");
List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
updatedAuthorities.add(authority);
updatedAuthorities.addAll(oldAuthorities);
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
SecurityContextHolder.getContext().getAuthentication().getCredentials(),
updatedAuthorities));
chain.doFilter(request, response);
}
}
之后,您可以使用以下语句检查您的角色:@PreAuthorize("hasRole('ROLE_TEAMLEADER')")
然后,您可以在spring-security-context
对象的帮助下访问用户角色:SecurityContextHolder.getContext().getAuthentication().getAuthorities()
根据其结果,您现在可以根据此对象中存储的角色自定义答案。例如,您可以在/userData
上实现如下所示的 RestCall:
@GetMapping("/userData")
public List<Object> getUserData() {
List<SimpleGrantedAuthority> roles = (List<SimpleGrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
SimpleGrantedAuthority authorityTeamLeader = new SimpleGrantedAuthority("ROLE_TEAMLEADER");
List<Object> result = new ArrayList<>();
if (roles.contains(authorityTeamLeader)) {
result = getAllUsers();
} else {
result = getPersonalUser(roles);
}
return result;
}