Изменение ответа на сбой аутентификации с помощью LiftRules.responseTransformers

#scala #lift #basic-authentication

#scala #отменить #базовая аутентификация

Вопрос:

Я использую приведенный ниже код, чтобы иметь базовую аутентификацию 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 
      } 
    }
  

Я не получаю измененный ответ для URL-адресов в RestApiHelper
объект.
Может кто-нибудь, пожалуйста, указать мне, как я могу изменить ответ для
URL-адреса Rest Api в случае несанкционированного ответа. Я не собираюсь делать
это с использованием кодов состояния. Поскольку я создаю API, который будет использоваться
мобильные приложения с управляемыми сервером ответами на ошибки для обеспечения согласованности и
множество других факторов.

ОБНОВЛЕНИЕ решения: этот следующий переопределенный класс case, основанный на ответе 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)
    }
  }
}
  

Ответ №1:

У меня была та же проблема с несанкционированным ответом Lift по умолчанию. Мое решение состояло в переопределении unauthorizedResponse метода HttpAuthentication признака. Вот пример кода:

   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)
    }
  }