【问题标题】:Which exception should be thrown, when Spring SecurityContextHolder returns null on getPrincipal?当 Spring SecurityContextHolder 在 getPrincipal 上返回 null 时,应该抛出哪个异常?
【发布时间】:2020-02-18 05:04:09
【问题描述】:

哪个异常最适合描述 RESTful 设计中缺少 Spring Security Principal,例如,当我从 SecurityContextHolder.getContext().getAuthentication().getPrincipal() 获取 Principal 时得到 null

我有一个带有自定义授权服务的项目,其中一部分需要有关已登录的委托人以及他拥有哪些权限的信息。

一些(但不是全部)REST 端点也受到 Spring Security 的保护。

然而系统变得越来越大并且可能发生错误,未经授权的用户将通过控制器层,并试图通过自定义授权服务访问受保护的数据。

一方面,最适合的异常似乎是AccessDeniedException(Http 403),但另一方面,抛出 500 或 404 以“隐藏”请求的存在可能是一种更安全的方法资源。

我想到了以下例外:

  • HttpStatus: 500 由org.springframework.security.access.AuthorizationServiceException 引起
  • HttpStatus: 403 org.springframework.security.access.AccessDeniedException
  • HttpStatus: 500 caused by java.lang.IllegalStateException
  • HttpStatus: 500 caused by java.lang.NullPointerException

我不相信哪种方法更好 - 禁止、隐藏或抛出内部服务器错误。

【问题讨论】:

    标签: java spring rest spring-security


    【解决方案1】:

    如果您使用的是 Spring Security 和自定义授权服务,您可能会遇到这样的情况:

    @Component
    public class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl {
        private final String HOME_PAGE = "/index.html";
    
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    
            if (auth != null) {
    
                if (auth instanceof AnonymousAuthenticationToken) {
                    response.sendRedirect("/#/login");
                    super.handle(request, response, e);
                    return;
                }
    
                if (auth.getAuthorities().iterator().next().getAuthority().equals("ROLE_EMPLOYEE") || auth.getAuthorities().iterator().next().getAuthority().equals("ROLE_ADMIN") ) {
                     response.sendRedirect("/dashboard/Dashboard.xhtml");
                     super.handle(request, response, e);
                     return;
                }     
                 response.sendRedirect("/#/dashboard/user");        
            }
            super.handle(request, response, e);
        }
    }  
    

    在您的情况下,在应用程序中,我宁愿建议重定向到登录屏幕 - 如上所示 - 并带有类似 Please log in 的消息。

    在 API 中,我会返回 404 - Resource not found 响应。

    【讨论】:

    • 对不起,但我没有提到,几个 REST 端点不受保护,例如。他们有 Spring Security permitAll() 。我最担心的是,开发人员可能会返回在另一个不受保护的 REST 端点上工作的敏感数据。这就是我引入另一层安全性的原因。因此,您重定向到登录页面的第一个答案将不适用于我的解决方案。
    • 你回答的第二部分:你能详细说明一下,你为什么会选择 404 响应?您是否参考了一些行业标准?
    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2018-07-27
    • 2012-12-22
    • 2012-06-08
    相关资源
    最近更新 更多