【问题标题】:Modify behavior of Spring @RolesAllowed修改 Spring @RolesAllowed 的行为
【发布时间】:2015-11-26 03:48:39
【问题描述】:

我正在使用 Spring @RolesAllowed 来保护我的 API(方法),但我想更改从未经授权的用户调用方法时发生的情况。当前的行为是 Spring 抛出 HTTP 403 错误。这很好,但我只想在 403 响应的正文中添加一个额外的错误代码,以便能够区分不同场景中的拒绝访问错误。

我很难弄清楚@RolesAllowed 注释的实现位置。有人遇到过吗?或者试图修改它的行为?

我的控制器中的方法目前如下所示:

@RolesAllowed({"ROLE_DEFENDANT", "ROLE_ADMIN"})
@RequestMapping(method = RequestMethod.POST, value = "/{caseId}/owner")
public ResponseEntity<?> assignOwner(@PathVariable String caseId) {

    // method implementation

}

【问题讨论】:

    标签: java spring spring-mvc spring-security spring-annotations


    【解决方案1】:

    您正在尝试做的事情,无需修改注释即可完成。

    在您的 Spring 配置中,您可以指定一个 AccessDeniedHandler bean,当 Spring Security 确定不允许您的用户执行他们尝试执行的操作时,该 bean 将被调用。

    拒绝访问处理程序非常简单:

    public class CustomDefaultAccessDeniedHandler implements AccessDeniedHandler {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
        }
    
    }
    

    AuthenticationProvider 的示例可以为您提供有关失败原因的更多信息:

    public class CustomAuthenticationProvider implements AuthenticationProvider {
        @Autowired
        private UserService userService;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
            String username = String.valueOf(auth.getPrincipal().toString());
            String password = String.valueOf(auth.getCredentials());
    
            if(username.isEmpty() || password.isEmpty()){
                throw new UsernameNotFoundException("You pudding, there is no username or password");
            } else {
                SystemUser user = userService.findByUsername(username);
                if(user == null){
                    throw new UsernameNotFoundException("No user exists, stop hacking");
                }
                //Do more stuff here to actually apply roles to the AuthToken etc
                return new UsernamePasswordAuthenticationToken(username, null, authorities);
    
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复!我实际上已经有一个AuthenticationFailureHandler。我缺少的是一个 AccessDeniedHandler。在您的回答中,您正确地提到了 AccessDeniedHandler,但随后给出了 AuthenticationFailureHandler 的示例。如果您更新代码示例以使其准确无误,我会将您的答案标记为已选择。
    【解决方案2】:

    另一种方法是使用异常处理程序类和@ExceptionHandler 注释。

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(AccessDeniedException.class)
        public ResponseEntity<?> handleAccessDenied(HttpServletRequest request, AccessDeniedException ex) {
    
            // exception handling logic
            if (request.getUserPrincipal() == null) {
                // user is not logged in
            } else {
                // user is logged in but doesn't have permission to the requested resource
            }
    
            // return whatever response you'd like
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2013-12-30
      • 2021-02-23
      • 2014-07-27
      • 2023-02-25
      • 2014-05-08
      • 1970-01-01
      • 2016-12-29
      • 2010-11-07
      • 2015-03-31
      相关资源
      最近更新 更多