首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring Security @Secured即使有正确的授权也拒绝访问

Spring Security @Secured即使有正确的授权也拒绝访问
EN

Stack Overflow用户
提问于 2021-08-05 17:42:13
回答 3查看 964关注 0票数 2

我的应用程序是一个springboot应用程序(2.4.0),我在spring安全性方面遇到了一些问题。我肯定这是一些简单的细节,但我就是看不见。

基本上,我从数据库中读取一个用户“角色”,并将其添加到GrantedAuthorities列表中的UserDetails中。然后,我使用@Secured在控制器中保护我的方法。我已经证实校长有GrantedAuthority.但是@Secured每次都否认这一点。

配置:

代码语言:javascript
复制
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)

我使用JWT,所以我有一个过滤器来创建基于它的用户:

代码语言:javascript
复制
@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:

代码语言:javascript
复制
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();

最后,我的安全方法:

代码语言:javascript
复制
@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,并将其添加到方法中,以确认它具有授予的权限:

代码语言:javascript
复制
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以完成请求

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-08-05 19:00:20

见Ken .的评论。

您正在测试的GrantedAuthority“验证”只是一个权威,但是您正在测试注释中的"ROLE_VALIDATING“。我不确定@Secured是否接受权威,我发现的所有例子都是角色。如果要使用角色,您可能需要测试@PreAuthorize(“hasAuthority(‘验证’)”),或者将权限重命名为"ROLE_VALIDATING“。- 24分钟前肯·S

对于那些跟随我所做的更改的人来说,要么切换到hasAuthority,要么使用@PreAuthorize注释。或者我改变了我的userDetailsService:

代码语言:javascript
复制
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new SimpleGrantedAuthority(String.format("ROLE_%s", user.getStatus())));

相关:Spring Security/Spring Boot - How to set ROLES for users

票数 3
EN

Stack Overflow用户

发布于 2022-03-29 02:33:52

您可以使用另一个注释,而不是将前缀"ROLE“添加到当局并使用@Secured:

@PreAuthorize("AnyAuthority('some-authority')")

如果要确定多个权限,可以通过以下方式对该方法进行注释:

( @PreAuthorize("hasAnyAuthority({'some-authority',‘read’}))

票数 1
EN

Stack Overflow用户

发布于 2022-04-05 17:19:06

在我的例子中,我从Spring转换为Spring。显然,Spring增加了它的注释语法的严格性。能够解析这个语法来识别两个不同的角色:

代码语言:javascript
复制
@PreAuthorize("hasAnyRoles('foo, bar')")

但是Spring Boot没有。Spring Boot要求我添加更多的撇号:

代码语言:javascript
复制
@PreAuthorize("hasAnyRoles('foo', 'bar')")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68671255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档