使用 LiftRules.responseTransformers 修改身份验证失败的响应

发布于 2024-11-03 02:05:52 字数 2488 浏览 1 评论 0原文

我正在使用以下代码在我的应用程序中进行 HTTP 基本身份验证,并且 转换未经授权访问情况下的响应。它不是 在职的。这里出了什么问题?

    // Http Basic Authentication 
    LiftRules.authentication = HttpBasicAuthentication("xxx") { 
      case (userName, userPass, _) => { 
        Console.println("Authenticating: " + userName) 
        User.find("userName", userName).map { 
          user => 
            if (user.password.isMatch(userPass)) { 
              Account.authenticatedUser.setFieldsFromDBObject(user.asDBObject) 
              userRoles(AuthRole("authorisedUser")) 
              Console.println("Success: " + userName) 
              true 
            } 
            else { 
              Console.println("Failed: " + userName) 
              false 
            } 
        } openOr false 
      } 
    } 

    LiftRules.responseTransformers.append { 
      resp => resp match { 
        case UnauthorizedResponse("xxx") => 
          Console.println("Responding modified..."); 
          JsonUnauthorizedResponse(("error" -> "Incorrect username or password")) 

        case x => Console.println("Responding..."); x 
      } 
    }

我没有收到 RestApiHelper 中 URL 的修改响应 目的。 有人可以指出我如何修改该响应 其余 Api URL,以防未经授权的响应。我不想做 它使用状态代码。因为我正在创建一个供使用的 API 具有服务器控制错误响应的移动应用程序,以确保一致性和 还有很多其他因素。

解决方案更新: 以下基于 CheatEx 答案的重写案例类对我有用:

  case class JsonHttpBasicAuthentication(realmName: String)(func: PartialFunction[(String, String, Req), Boolean]) extends HttpAuthentication {

  def credentials(r: Req): Box[(String, String)] = {
    header(r).flatMap(auth => {
      val decoded = new String(Base64.decodeBase64(auth.substring(6, auth.length).getBytes)).split(":").toList
      decoded match {
        case userName :: password :: _ => Full((userName, password))
        case userName :: Nil => Full((userName, ""))
        case _ => Empty
      }
    }
    )
  }

  override def realm = realmName

  def verified_? = {
    case (req) => {
      credentials(req) match {
        case Full((user, pwd)) if (func.isDefinedAt(user, pwd, req)) =>
          func(user, pwd, req)
        case _ => false
      }
    }
  }

  override def unauthorizedResponse: UnauthorizedResponse = new UnauthorizedResponse(realm) {
    override def toResponse = {
      val errResp: JValue = ("error" -> "Incorrect username or password")
      InMemoryResponse(errResp.toString.getBytes("UTF-8"),
      S.getHeaders(Nil), S.responseCookies, 200)
    }
  }
}

I am using the below code to have HTTP Basic Auth in my app and
transform the response in case of Unauthorised access. It is not
working. Whats wrong here?

    // Http Basic Authentication 
    LiftRules.authentication = HttpBasicAuthentication("xxx") { 
      case (userName, userPass, _) => { 
        Console.println("Authenticating: " + userName) 
        User.find("userName", userName).map { 
          user => 
            if (user.password.isMatch(userPass)) { 
              Account.authenticatedUser.setFieldsFromDBObject(user.asDBObject) 
              userRoles(AuthRole("authorisedUser")) 
              Console.println("Success: " + userName) 
              true 
            } 
            else { 
              Console.println("Failed: " + userName) 
              false 
            } 
        } openOr false 
      } 
    } 

    LiftRules.responseTransformers.append { 
      resp => resp match { 
        case UnauthorizedResponse("xxx") => 
          Console.println("Responding modified..."); 
          JsonUnauthorizedResponse(("error" -> "Incorrect username or password")) 

        case x => Console.println("Responding..."); x 
      } 
    }

I am not getting the modified response for the URLs in RestApiHelper
object.
Can somebody please point me to how I can modify the response for the
Rest Api Urls in case of unauthorizedResponse. I do not intend to do
it using Status Codes. Since I am creating an API to be consumed by
mobile apps with server controlled error responses for consistency and
a lot of other factors.

Solution UPDATE:
This following overridden case class based on the answer by CheatEx worked for me:

  case class JsonHttpBasicAuthentication(realmName: String)(func: PartialFunction[(String, String, Req), Boolean]) extends HttpAuthentication {

  def credentials(r: Req): Box[(String, String)] = {
    header(r).flatMap(auth => {
      val decoded = new String(Base64.decodeBase64(auth.substring(6, auth.length).getBytes)).split(":").toList
      decoded match {
        case userName :: password :: _ => Full((userName, password))
        case userName :: Nil => Full((userName, ""))
        case _ => Empty
      }
    }
    )
  }

  override def realm = realmName

  def verified_? = {
    case (req) => {
      credentials(req) match {
        case Full((user, pwd)) if (func.isDefinedAt(user, pwd, req)) =>
          func(user, pwd, req)
        case _ => false
      }
    }
  }

  override def unauthorizedResponse: UnauthorizedResponse = new UnauthorizedResponse(realm) {
    override def toResponse = {
      val errResp: JValue = ("error" -> "Incorrect username or password")
      InMemoryResponse(errResp.toString.getBytes("UTF-8"),
      S.getHeaders(Nil), S.responseCookies, 200)
    }
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蝶…霜飞 2024-11-10 02:05:52

我对电梯默认的未经授权的响应也有同样的问题。我的解决方案是重写 HttpAuthentication 特征的 unauthorizedResponse 方法。
这是一个代码示例:

  private object MyHttpAuth extends HttpAuthentication {

    override def realm: String = "MyApp"

    def verified_? : PartialFunction[Req, Boolean] = {
      case req: Req => getUser(req) match {
        case Some(userId) => {
          userRoles(AuthRole(userId)::Nil)
          true
        }
        case None => false
      }
    }

    override def unauthorizedResponse: UnauthorizedResponse = new UnauthorizedResponse(realm) {
      override def toResponse = InMemoryResponse(Array(), Nil, Nil, 401)
    }
  }

I had the same problem with the Lift's default unauthorised response. My solution was to override unauthorizedResponse method of the HttpAuthentication trait.
Here is a code sample:

  private object MyHttpAuth extends HttpAuthentication {

    override def realm: String = "MyApp"

    def verified_? : PartialFunction[Req, Boolean] = {
      case req: Req => getUser(req) match {
        case Some(userId) => {
          userRoles(AuthRole(userId)::Nil)
          true
        }
        case None => false
      }
    }

    override def unauthorizedResponse: UnauthorizedResponse = new UnauthorizedResponse(realm) {
      override def toResponse = InMemoryResponse(Array(), Nil, Nil, 401)
    }
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文