Akka(42): Http:身份验证 - authentication, autorization and use of raw headers
当我们把Akka-http作为数据库数据交换工具时,数据是以Source[ROW,_]形式存放在Entity里的。很多时候除数据之外我们可能需要进行一些附加的信息传递如对数据的具体处理方式等。我们可以通过Akka-http的raw-header来实现附加自定义消息的传递,这项功能可以通过Akka-http提供的raw-header筛选功能来实现。在客户端我们把附加消息放在HttpRequest的raw header里,如下:
import akka.http.scaladsl.model.headers._
val request = HttpRequest(HttpMethods.POST,uri = s"http://localhost:8011/rows")
.addHeader(RawHeader("action","insert:county"))
在这里客户端注明上传数据应插入county表。服务端可以像下面这样获取这项信息:
optionalHeaderValueByName("action") {
case Some(action) =>
entity(asSourceOf[County]) { source =>
val futofNames: Future[List[String]] =
source.runFold(List[String](""))((acc, b) => acc ++ List(b.name))
complete(s"Received rows for $action")
}
case None => complete ("No action specified!")
}
Akka-http通过Credential类的Directive提供了authentication和authorization。在客户端可以用下面的方法提供自己的用户身份信息:
import akka.http.scaladsl.model.headers._
val request = HttpRequest(HttpMethods.POST,uri = s"http://localhost:8011/rows")
.addHeader(RawHeader("action","insert:county"))
.addCredentials(BasicHttpCredentials("john", "p4ssw0rd"))
服务端对客户端的身份验证处理方法如下:
import akka.http.scaladsl.server.directives.Credentials
def myUserPassAuthenticator(credentials: Credentials): Future[Option[User]] = {
implicit val blockingDispatcher = httpSys.dispatchers.lookup("akka-httpblocking-ops-dispatcher")
credentials match {
case p @ Credentials.Provided(id) =>
Future {
// potentially
if (p.verify("p4ssw0rd")) Some(User(id))
else None
}
case _ => Future.successful(None)
}
} case class User(name: String)
val validUsers = Set("john","peter","tiger","susan")
def hasAdminPermissions(user: User): Future[Boolean] = {
implicit val blockingDispatcher = httpSys.dispatchers.lookup("akka-httpblocking-ops-dispatcher")
Future.successful(validUsers.contains(user.name))
}
下面是Credential-Directive的使用方法:
authenticateBasicAsync(realm = "secure site", userPassAuthenticator) { user =>
authorizeAsync(_ => hasPermissions(user)) {
withoutSizeLimit {
handleExceptions(postExceptionHandler) {
optionalHeaderValueByName("action") {
case Some(action) =>
entity(asSourceOf[County]) { source =>
val futofNames: Future[List[String]] =
source.runFold(List[String](""))((acc, b) => acc ++ List(b.name))
complete(s"Received rows for $action sent from $user")
}
case None => complete(s"$user did not specify action for uploaded rows!")
}
}
}
}
}
下面是本次讨论的示范代码:
客户端:
import akka.actor._
import akka.stream._
import akka.stream.scaladsl._
import akka.http.scaladsl.Http
import scala.util._
import akka._
import akka.http.scaladsl.common._
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.common.EntityStreamingSupport
import akka.http.scaladsl.model._
import spray.json._ trait MyFormats extends SprayJsonSupport with DefaultJsonProtocol
object Converters extends MyFormats {
case class County(id: Int, name: String)
implicit val countyFormat = jsonFormat2(County)
} object HttpClientDemo extends App {
import Converters._ implicit val sys = ActorSystem("ClientSys")
implicit val mat = ActorMaterializer()
implicit val ec = sys.dispatcher implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json() import akka.util.ByteString
import akka.http.scaladsl.model.HttpEntity.limitableByteSource val source: Source[County,NotUsed] = Source( to ).map {i => County(i, s"广西壮族自治区地市县编号 #$i")}
def countyToByteString(c: County) = {
ByteString(c.toJson.toString)
}
val flowCountyToByteString : Flow[County,ByteString,NotUsed] = Flow.fromFunction(countyToByteString) val rowBytes = limitableByteSource(source via flowCountyToByteString) import akka.http.scaladsl.model.headers._
val request = HttpRequest(HttpMethods.POST,uri = s"http://localhost:8011/rows")
.addHeader(RawHeader("action","insert:county"))
.addCredentials(BasicHttpCredentials("john", "p4ssw0rd")) val data = HttpEntity(
ContentTypes.`application/json`,
rowBytes
) def uploadRows(request: HttpRequest, dataEntity: RequestEntity) = {
val futResp = Http(sys).singleRequest(
request.copy(entity = dataEntity)
)
futResp
.andThen {
case Success(r@HttpResponse(StatusCodes.OK, _, entity, _)) =>
entity.dataBytes.map(_.utf8String).runForeach(println)
case Success(r@HttpResponse(code, _, _, _)) =>
println(s"Upload request failed, response code: $code")
r.discardEntityBytes()
case Success(_) => println("Unable to Upload file!")
case Failure(err) => println(s"Upload failed: ${err.getMessage}") }
} uploadRows(request,data) scala.io.StdIn.readLine() sys.terminate() }
服务端:
import akka.actor._
import akka.stream._
import akka.stream.scaladsl._
import akka.http.scaladsl.Http
import akka._
import akka.http.scaladsl.common._
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import scala.concurrent._
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model._ trait MyFormats extends SprayJsonSupport with DefaultJsonProtocol
object Converters extends MyFormats {
case class County(id: Int, name: String)
val source: Source[County, NotUsed] = Source( to ).map { i => County(i, s"中国广东省地区编号 #$i") }
implicit val countyFormat = jsonFormat2(County)
} object HttpServerDemo extends App { import Converters._ implicit val httpSys = ActorSystem("httpSystem")
implicit val httpMat = ActorMaterializer()
implicit val httpEC = httpSys.dispatcher implicit val jsonStreamingSupport = EntityStreamingSupport.json()
.withParallelMarshalling(parallelism = , unordered = false) def postExceptionHandler: ExceptionHandler =
ExceptionHandler {
case _: RuntimeException =>
extractRequest { req =>
req.discardEntityBytes()
complete((StatusCodes.InternalServerError.intValue, "Upload Failed!"))
}
} import akka.http.scaladsl.server.directives.Credentials
def userPassAuthenticator(credentials: Credentials): Future[Option[User]] = {
implicit val blockingDispatcher = httpSys.dispatchers.lookup("akka-httpblocking-ops-dispatcher")
credentials match {
case p @ Credentials.Provided(id) =>
Future {
// potentially
if (p.verify("p4ssw0rd")) Some(User(id))
else None
}
case _ => Future.successful(None)
}
} case class User(name: String)
val validUsers = Set("john","peter","tiger","susan")
def hasPermissions(user: User): Future[Boolean] = {
implicit val blockingDispatcher = httpSys.dispatchers.lookup("akka-httpblocking-ops-dispatcher")
Future.successful(validUsers.contains(user.name))
} val route =
path("rows") {
get {
complete {
source
}
} ~
post {
authenticateBasicAsync(realm = "secure site", userPassAuthenticator) { user =>
authorizeAsync(_ => hasPermissions(user)) {
withoutSizeLimit {
handleExceptions(postExceptionHandler) {
optionalHeaderValueByName("action") {
case Some(action) =>
entity(asSourceOf[County]) { source =>
val futofNames: Future[List[String]] =
source.runFold(List[String](""))((acc, b) => acc ++ List(b.name))
complete(s"Received rows for $action sent from $user")
}
case None => complete(s"$user did not specify action for uploaded rows!")
}
}
}
}
}
}
} val (port, host) = (,"localhost") val bindingFuture = Http().bindAndHandle(route,host,port) println(s"Server running at $host $port. Press any key to exit ...") scala.io.StdIn.readLine() bindingFuture.flatMap(_.unbind())
.onComplete(_ => httpSys.terminate()) }
Akka(42): Http:身份验证 - authentication, autorization and use of raw headers的更多相关文章
- Akka(42): Http:身份验证 - authentication, authorization and use of raw headers
当我们把Akka-http作为数据库数据交换工具时,数据是以Source[ROW,_]形式存放在Entity里的.很多时候除数据之外我们可能需要进行一些附加的信息传递如对数据的具体处理方式等.我们可以 ...
- 也谈Asp.net 中的身份验证
钱李峰 的这篇博文<Asp.net中的认证与授权>已对Asp.net 中的身份验证进行了不错实践.而我这篇博文,是从初学者的角度补充了一些基础的概念,以便能有个清晰的认识. 一.配置安全身 ...
- .net core使用ocelot---第二篇 身份验证
简介原文链接 .net core使用ocelot---第一篇 简单使用 接上文,我将继续介绍使用asp.net core 创建API网关,主要介绍身份验证(authentication )相 ...
- 学学dotnet core中的身份验证和授权-1-概念
前言 身份验证: Authentication 授权: Authorization net core 中的身份验证和授权这两个部分,是相辅相成的.当初我在学在部分的时候,是看的 net core 官网 ...
- Angular 应用中的登陆与身份验证
Angular 经常会被用到后台和管理工具的开发,这两类都会需要对用户进行鉴权.而鉴权的第一步,就是进行身份验证.由于 Angular 是单页应用,会在一开始,就把大部分的资源加载到浏览器中,所以就更 ...
- 【记录】ASP.NET MVC 4/5 Authentication 身份验证无效
在 ASP.NET MVC 4/5 应用程序发布的时候,遇到一个问题,在本应用程序中进行身份验证是可以,但不能和其他"二级域名"共享,在其他应用程序身份验证,不能和本应用程序共享, ...
- SQL Server安全(2/11):身份验证(Authentication)
在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Se ...
- 发布Restful服务时出现IIS 指定了身份验证方案错误时的解决方案(IIS specified authentication schemes)
发布RESTful服务,当访问.svc文件时出现如下错误时: IIS 指定了身份验证方案“IntegratedWindowsAuthentication, Anonymous”,但绑定仅支持一种身份验 ...
- Zend Framework 2参考Zend\Authentication(摘要式身份验证)
Zend Framework 2参考Zend\Authentication(摘要式身份验证) 介绍 摘要式身份验证是HTTP身份验证的方法,提高了基本身份验证时提供的方式进行身份验证,而无需在网络上以 ...
随机推荐
- spark在yarn-cluster模式,错误查找方法
yarn logs -applicationId application_xxxx_xxx 可选(">exception")
- window下eclipse4.5+hadoop2.6.1开发环境配置
1.准备: eclipse4.5,hadoop2.6.1,hadoop-eclipse-plugin-2.6.0.jar. 2.eclipse配置 eclipse->windows->Pr ...
- TinyXML2的使用
-----------------------------------------------------------------2015年7月21日16:37:53----------------- ...
- 2017广东工业大学程序设计竞赛决赛-tmk买礼物
tmk买礼物 Description 今天是校赛的日子,为了庆祝这么喜庆的日子,TMK打算买些礼物给女票LSH庆祝一下. TMK进入了雪梨超市,然后刚踏入的一瞬间,店主就对TMK说:“恭喜你成为了本店 ...
- Formatting the event object
尽量将IE与DOM函数事件对象不同的性质或方法转成DOM标准 EventUtil.formatEvent = function (oEvent) { if (isIE && ...
- 「Vue」起步 - vue-router路由与页面间导航
vue-router 我们知道路由定义了一系列访问的地址规则,路由引擎根据这些规则匹配找到对应的处理页面,然后将请求转发给页进行处理.可以说所有的后端开发都是这样做的,而前端路由是不存在"请 ...
- TOMCAT启动到一半停止如何解决
当你的项目过大的时候,往往会导致你的TOMCAT启动时间过长,启动失败,遇到该情况可以试一下下面两招: TOmcat启动到一半的时候停止了,以下原因: 1. tomcat启动时间超过了设置时间: 解 ...
- NodeJS 常用模块积累
cluster&forever cluster & forever 虽然 nodejs 原生已经提供了 cluster 模块,大部分情况下可以满足我们的基本需求,但这两个模块 clus ...
- Java多线程学习之线程池源码详解
0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...
- 使用face_recognition批量识别图片中的人数
#使用face_recognition实现从图片中选中人数并分别输出txtimport face_recognition import cv2 import os fin = 'D:\\Users\\ ...