【发布时间】:2021-10-10 17:43:28
【问题描述】:
我的应用程序是一个 springboot 应用程序 (2.4.0),我在 spring 安全方面遇到了一些问题。我确信它是一些简单的细节,但我就是看不到它。
基本上发生的事情是我从数据库中读取了一个用户“角色”并将其添加到 UserDetails 中的 GrantedAuthorities 列表中。然后我使用@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!");
}
果然,当我执行代码时,它会更新我的记录并注销“我有这个角色!”。所以看起来 A) 用户正在由 userDetailsService 正确填充。 B) SecurityContextHolder 中的身份验证已正确设置。 C) 用户实际上确实拥有 GrantedAuthority。
但@Secured 仍然拒绝访问。
当我启用调试日志记录时,我会在请求被拒绝时看到以下内容。
初始化 Spring DispatcherServlet 'dispatcherServlet' 初始化 Servlet 'dispatcherServlet' 3 ms 内完成初始化 保护 PUT /api/private/auth/activate 将 SecurityContextHolder 设置为空 SecurityContext 具有属性 [authenticated] 的授权过滤器调用 [PUT /api/private/auth/activate] 安全 PUT /api/private/auth/activate 无法授权 ReflectiveMethodInvocation: public org.springframework.http.ResponseEntity net.theblackchamber.map.dashboard.controller.PrivateController.activateAccount(org.springframework.security.core.Authentication);目标属于 [net.theblackchamber.map.dashboard.controller.PrivateController] 类,具有 [ROLE_VALIDATING] 属性 响应 403 状态码 清除 SecurityContextHolder 以完成请求 保护 PUT /错误 将 SecurityContextHolder 设置为空 SecurityContext 将 SecurityContextHolder 设置为匿名 SecurityContext 安全的 PUT /错误 清除 SecurityContextHolder 以完成请求
【问题讨论】:
-
您正在测试的GrantedAuthority“VALIDATING”只是一个权限,但您正在测试注释中的“ROLE_VALIDATING”。我不确定@Secured 是否接受授权,我发现的所有示例都是角色。如果您想使用角色,您可能需要测试 @PreAuthorize("hasAuthority('VALIDATING')") 或将权限重命名为“ROLE_VALIDATING”。
-
还有一个小东西整个早上都在盯着我看!非常感谢。
标签: java spring-boot spring-security