我的应用程序是一个springboot应用程序(2.4.0),我在spring安全性方面遇到了一些问题。我肯定这是一些简单的细节,但我就是看不见。
基本上,我从数据库中读取一个用户“角色”,并将其添加到GrantedAuthorities列表中的UserDetails中。然后,我使用@Secured在控制器中保护我的方法。我已经证实校长有GrantedAuthority.但是@Secured每次都否认这一点。
配置:
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)我使用JWT,所以我有一个过滤器来创建基于它的用户:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}我的userDetailsService填充GrantedAuthorities:
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(user.getStatus().name()));
return UserDetailsImpl.builder().username(user.getUsername()).guid(user.getGuid()).name(user.getName())
.password(user.getPassword()).status(user.getStatus()).authorities(authorities).build();最后,我的安全方法:
@PutMapping("/auth/activate")
@Secured("ROLE_VALIDATING")
public ResponseEntity<?> activateAccount(Authentication authentication) {
accountService.activateAccount(authentication.getName());
return ResponseEntity.ok().body(new MessageResponse("Account Activated"));
}因此,为了排除故障,我删除了@Secured并验证了该方法的执行,没有任何问题。然后我离开@Secured,并将其添加到方法中,以确认它具有授予的权限:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("VALIDATING"))) {
LOG.info("I has the role!");
}当然,当我执行代码时,它会更新我的记录并注销“我有这个角色!”。因此,userDetailsService似乎正确地填充了A)用户。( B)正在正确设置SecurityContextHolder中的身份验证。( C)用户实际上拥有正确的GrantedAuthority。
但是@Secured仍然拒绝访问。
当我启用调试日志记录时,当请求被拒绝时,我会看到以下内容。
启动Spring DispatcherServlet 'dispatcherServlet‘初始化Servlet 'dispatcherServlet’在3ms内完成初始化,保护PUT /api/私有/auth/activate Set SecurityContextHolder,以空SecurityContext授权筛选器调用PUT /api/私有/auth/activate,属性验证为安全的PUT /api/私有/auth/dispatcherServlet未能授权ReflectiveMethodInvocation:公共org.springframework.http.ResponseEntity SecurityContextHolder目标属于net.theblackchamber.map.dashboard.controller.PrivateController类,属性为ROLE_VALIDATING,响应403个状态代码,清除了SecurityContextHolder以完成请求保护,将/error集SecurityContextHolder为空SecurityContext集,SecurityContextHolder为匿名SecurityContext,安全放置/error已清除SecurityContextHolder以完成请求
发布于 2021-08-05 19:00:20
见Ken .的评论。
您正在测试的GrantedAuthority“验证”只是一个权威,但是您正在测试注释中的"ROLE_VALIDATING“。我不确定@Secured是否接受权威,我发现的所有例子都是角色。如果要使用角色,您可能需要测试@PreAuthorize(“hasAuthority(‘验证’)”),或者将权限重命名为"ROLE_VALIDATING“。- 24分钟前肯·S
对于那些跟随我所做的更改的人来说,要么切换到hasAuthority,要么使用@PreAuthorize注释。或者我改变了我的userDetailsService:
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(String.format("ROLE_%s", user.getStatus())));发布于 2022-03-29 02:33:52
您可以使用另一个注释,而不是将前缀"ROLE“添加到当局并使用@Secured:
@PreAuthorize("AnyAuthority('some-authority')")
如果要确定多个权限,可以通过以下方式对该方法进行注释:
( @PreAuthorize("hasAnyAuthority({'some-authority',‘read’}))
发布于 2022-04-05 17:19:06
在我的例子中,我从Spring转换为Spring。显然,Spring增加了它的注释语法的严格性。能够解析这个语法来识别两个不同的角色:
@PreAuthorize("hasAnyRoles('foo, bar')")但是Spring Boot没有。Spring Boot要求我添加更多的撇号:
@PreAuthorize("hasAnyRoles('foo', 'bar')")https://stackoverflow.com/questions/68671255
复制相似问题