【问题标题】:How can I ask for credentials after Spring Security ACL has thrown an AccessDeniedException?在 Spring Security ACL 抛出 AccessDeniedException 后,如何请求凭据?
【发布时间】:2014-01-29 20:53:32
【问题描述】:

我正在使用 Grails 2.2.3 和 Spring Security ACL 插件 1.1.1,我希望有一个对公众开放的 URL,并且使用 @PostAuthorize 注释的服务层可以保护资源。我们这样做是因为要确定用户是否有权访问特定对象,我们需要先查看该对象。

我想做的是在控制器层捕获 AccessDeniedException,然后让浏览器请求凭据并重试。我尝试了将响应状态设置为 401 并重定向回自身以重试的天真的方法。我遇到的问题是浏览器从未要求提供凭据。

要将其放入代码中,我想做的是在控制器层中:

@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def controllerAction() {
   try {
      someService.action()
   } catch (AccessDeniedException ade) {
      // if logged in show FORBIDDEN, if not ask for credentials and try again
   }
}

而服务层只需:

@PostAuthorize("""returnObject.availability == 'ALL'""")
def action() {
   PersistedObject.findById(1)
}

感谢您的帮助!

【问题讨论】:

  • 您能否发布将响应状态设置为 401 并重定向回来的代码?无论如何,在您的情况下,可能有可能通过 ACL 授予对所有人可用的对象的访问权限,然后您不需要先加载对象来检查是否允许用户使用此类对象。只需授予例如对分配给所有用户的角色(例如 ROLE_USER)的读取权限。
  • 这就是我们已经在做的事情。重定向只是设置 response.status = 401, redirect(self)。重定向的问题是将状态设置为不要求登录的 302。问题不是匿名访问这些对象,而是匿名访问这些对象,然后如果请求用户名/密码失败。
  • 我不确定我是否正确理解了您的流程。您发送的是 401 还是 302 HTTP 响应?当您发送 302 HTTP 响应时,用户通常不会注意到,因为用户代理(例如 Web 浏览器)会自动重定向到 Location 标头中声明的 URL。无论如何, AccessDeniedException 并不意味着用户未通过身份验证,而是表示用户无权访问某些资源。正确的响应应该是 HTTP 403。可能最简单的方法是实现自定义 org.springframework.security.web.access.AccessDeniedHandler,它将返回您需要的任何内容。
  • 我为我之前的评论道歉,因为我似乎让你感到困惑。我了解 AccessDeniedException 意味着用户未获得授权,但在我的情况下,“用户”可能是匿名的。在这种情况下,我想发送 401,以便浏览器要求匿名用户进行身份验证并重试。如果用户不是匿名的,则发送 403。我不认为 AccessDeniedHandler 是我想要的,因为它将全局应用于我只希望这个端点以这种方式运行的所有端点。
  • 无论如何,请考虑如上所述在自定义处理程序中处理AccessDeniedException。然后,您只有专用于处理此类情况的组件,而不是散布在您的代码库中的几个代码块。在处理程序中,您可以根据请求 URL 发送不同的响应。

标签: grails spring-security spring-security-acl


【解决方案1】:

我最终解决了这个问题,结果发现我缺少一个需要连同 401 状态代码一起发送的标头。

要纠正我上面你想要做的事情是:

@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def controllerAction() {
   try {
      someService.action()
   } catch (AccessDeniedException ade) {
      if (!springSecurityService.isLoggedIn()) {
         response.setHeader 'WWW-Authenticate', 'Basic realm="Grails Realm"' // the missing line
         response.sendError HttpServletResponse.SC_UNAUTHORIZED 
   }
}

提交凭据后,我正在寻找的“重定向”会在浏览器中自动发生。我误认为需要特定于重定向的东西。

【讨论】:

    猜你喜欢
    • 2017-06-14
    • 2014-07-25
    • 1970-01-01
    • 2013-02-25
    • 2013-04-10
    • 2018-08-09
    • 2018-12-13
    • 1970-01-01
    • 2018-10-18
    相关资源
    最近更新 更多