Spray(14)Simple/Free/Complex Auth
We can have different auth in our spray framework.
Only Simple and Complex Auth need to have implementation class based on that.
In the AuthDirectives class, we need these kind of codes.
def localpointSimpleAuth = authenticate(new BrandUserSimpleSigAuthenticator(authDirectory)) & pathPrefix(Version) &optionalHeaderValueByName("Origin")
def localpointAuth = authenticate(new BrandUserSignatureAuthenticator(authDirectory)) & pathPrefix(Version) & optionalHeaderValueByName("Origin")
In the implementation, we usually just get some info from header and validate based on that.
package com.sillycat.localpoint.auth
import com.sillycat.localpoint.model.BrandUser
import org.joda.time.DateTime
import scala.concurrent.{ Future, ExecutionContext }
import spray.routing.authentication._
import com.sillycat.localpoint.auth.model._
import com.sillycat.localpointauth.directory.AuthDirectory
import com.sillycat.localpoint.auth.util.BrandCodeExtractor
import spray.http._
import spray.http.HttpHeaders.Authorization
import spray.util.pimpSeq
import com.typesafe.scalalogging.slf4j.Logging
import spray.routing.AuthenticationFailedRejection
import spray.routing.RequestContext
import scala.Some
import spray.routing.AuthenticationFailedRejection
import spray.routing.RequestContext
import scala.Some
import spray.routing.directives.{ RouteDirectives, MiscDirectives, BasicDirectives, MarshallingDirectives }
import spray.routing.directives.BasicDirectives._
import spray.routing.AuthenticationFailedRejection
import spray.routing.RequestContext
import scala.Some
import shapeless.{ HNil, :: }
import shapeless._
import spray.httpx.marshalling._
import spray.httpx.unmarshalling._
import spray.http._
class BrandUserSimpleSigAuthenticator(authDirectory: AuthDirectory)(implicit val executionContext: ExecutionContext) extends ContextAuthenticator[BrandUserWithPrivileges]
with Logging {
def apply(ctx: RequestContext) = {
val authRequestOption = getAuthRequest(ctx)
BrandCodeExtractor(ctx.request.uri.authority.host.address) match {
case Some(b) => {
authRequestOption match {
case Some(x) => {
checkSimpleSig(x, b)
}
case _ => {
logger.warn("authenticate fail, parse header fail.")
Future(Left(AuthenticationFailedRejection("Realm")))
}
}
}
case _ => {
logger.warn("authenticate fail, system can not parse the brand code from host URL.")
Future(Left(AuthenticationFailedRejection("Realm")))
}
}
}
def getAuthRequest(ctx: RequestContext): Option[String] = {
val uri = ctx.request.uri.path.toString
val authHeader = ctx.request.headers.findByType[`Authorization`]
val tokenString = authHeader match {
case Some(x) => {
logger.debug("Header is there, try get token string from header " + x)
x.value
}
case _ => {
logger.debug("Header is empty, Body is empty.")
""
}
}
Some(tokenString)
}
def checkSimpleSig(authRequest: String, brandCode: String) = {
Future {
// first load the user information to get the appId/ apisecretkey/ consolekey
authDirectory.gebBrandByCode(brandCode) match {
case Some(brand) => {
if ((QABrands.contains(brandCode)) || (brand.apiSecretKey == authRequest)) {
val privileges_set = Set("RESOURCE_" + "API", "RESOURCE_" + brandCode)
val brandUser = BrandUser(None, 1l, "", "", "", true, "", "", "", false, false, true, false, DateTime.now, 0, 0)
val user = BrandUserWithPrivileges(brandUser, brandCode, privileges_set)
Right(user)
} else {
logger.warn("authenticate fail, simple signature error, AuthRequest String=" + authRequest)
Left(AuthenticationFailedRejection("Realm"))
}
}
case _ => {
logger.warn("failed to retrieve auth info with brand '%s'".format(brandCode))
Left(AuthenticationFailedRejection("Realm"))
}
}
}
}
}
When we build the router in Spray, we will build the 3 types of auth.
package com.sillycat.localpoint.console.api
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.actorRef2Scala
import akka.io.IO
import akka.routing.FromConfig
import com.sillycat.localpoint.actors.AttributeDBImportActor
import spray.can.Http
import com.sillycat.localpoint.auth.LocalpointAuthDirectives
import com.sillycat.localpoint.auth.service.AbstractAuthService
import spray.routing.{ Directives, HttpService }
import com.typesafe.config.ConfigFactory
import com.sillycat.localpoint.model._
import com.sillycat.localpoint.auth.util.ResponseHeaderUtil
import com.sillycat.localpointauth.directory.{ MultiStoreUserRepositoryComponent, AuthDirectory }
object LocalpointBridgeAPIServer extends App {
implicit val system = ActorSystem()
val config = ConfigFactory.load()
assert(Profile.env == "environment." + config.getString("build.env"))
val serverAddress: String = config.getString("server.address")
val serverPort: Int = config.getInt("server.port")
val dal: DAL = DAL()
val handler = system.actorOf(Props[LocalpointBridgeAPIServiceActor])
system.actorOf(Props[AttributeDBImportActor].withRouter(FromConfig()), name = "AttributeDBImportRouter")
IO(Http) ! Http.Bind(handler, serverAddress, serverPort)
}
class LocalpointBridgeAPIServiceActor extends Actor with LocalpointConnector {
def actorRefFactory = context
def receive = runRoute(authSimpleRoute ~ authComplexRoute ~ authFreeRoute ~ baseOptions)
}
trait LocalpointConnector extends HttpService
with AttributeMetadataService
with CampaignService
with AttributeService
with ProfileService
with DeviceIdentifierService
with LocationService
with TagService
with LocalpointAuthDirectives
with Directives {
override implicit val dal: DAL = DAL.apply
val authDirectory = new AuthDirectory with MultiStoreUserRepositoryComponent {}
def baseOptions = {
optionalHeaderValueByName("Origin") { originHeader =>
respondWithHeaders(ResponseHeaderUtil.getCrossDomainHeaders(originHeader): _*) {
options {
complete {
"OK"
}
}
}
}
}
val authFreeRoute = {
optionalHeaderValueByName("Origin") { originHeader =>
respondWithHeaders(ResponseHeaderUtil.getCrossDomainHeaders(originHeader): _*) {
attributeAuthFreeRoutes()
}
}
}
val authSimpleRoute = {
localpointSimpleAuth { (user, version, originHeader) =>
respondWithHeaders(ResponseHeaderUtil.getCrossDomainHeaders(originHeader): _*) {
attributeAuthSimpleRoutes(user, version)
}
}
}
val authComplexRoute = {
//localpointAuth { (user, version) =>
localpointAuth { (user, version, originHeader) =>
respondWithHeaders(ResponseHeaderUtil.getCrossDomainHeaders(originHeader): _*) {
authorize(verifyPrivileges(_, user)) {
attributeMetadataRoutes(user, version) ~
attributeRoutes(user, version)
}
}
}
}
}
References:
相关推荐
- `simple_sploit`:这可能是一个基础的JIT Spray的实现,可能包括了代码生成、内存分配和喷射的逻辑。攻击者可能会使用一些开源的JIT库,如.NET的DynamicMethod或JavaScript的V8引擎,来生成和执行代码。 - `...
欢迎来到rest scala / spray / akka / slick / mysql示例 在研究scala / spray / akka / slick / mysql REST服务期间,我已经创建了这个项目。 它可以用来学习一些有关如何使用这些技术来创建REST服务的知识。 但是...
"knol-spray-auth" 项目可能是基于 Akka 和 Spray 构建的一个示例或模板,专注于身份验证(Authentication)功能。在 REST API 中,身份验证是确保只有授权用户能够访问受保护资源的关键步骤。该项目可能演示了如何...
在实际使用中,`spray-template-on_spray-can_1.3`可能是一个包含spray-template特定版本的库,用于与spray-can 1.3版兼容。这个压缩包文件可能包含了以下内容: - `spray-template`的Scala源码或编译后的JAR文件,...
在Linux和Android内核中,Heap Spray技术主要依赖于SLUB(Simple List-based Unified Buffer)内存分配器。SLUB是Linux和Android内核中的一种内存分配器,它是一种基于简单链表的内存分配算法。SLUB在分配内存时,会...
“Writing JIT-Spray Shellcode for fun and profit”这一主题深入探讨了如何利用Just-In-Time(JIT)编译器的特性来实施攻击,尤其关注绕过现代浏览器如Internet Explorer 8及其后续版本中的防御机制。以下是对该...
spray-actor-per-request, 使用每个请求模型中的参与者的示例 Spray 应用程序 每个请求的 Spray这个项目提供了一个示例 Spray 应用程序,它使用每个请求模型中的参与者。为什么要为每个HTTP请求启动一个参与者?轻松...
Spray and Wait是一种针对间歇连接移动网络(Intermittently Connected Mobile Networks,简称ICMN)的高效路由方案。ICMN是一类稀疏无线网络,其中大部分时间内源节点到目标节点之间不存在完整的路径,因此可以看作...
### JIT Spray技术详解 #### 摘要与背景 随着远程攻击变得越来越难以实施以及边界防御成为标准配置,客户端侧的远程攻击成为了攻击者的新选择。为了抑制客户端侧漏洞的爆发,现代Windows操作系统采用了诸如数据...
微服务原型 A 具有 Scala、Akka、Spray 和 Camel/ActiveMQ 的微服务原型。 基于 Typesafe Activator 模板。 项目包含: 使用示例 actor 轻松测试 Akka 系统具有完整 CORS 支持的基于喷雾的 RESTful API Actor 和 API...
The effect of Sb spray time on the structure of InAs/GaAs quantum dot (QD) systems with Sb spray prior to the capping of a GaAs layer was determined by a Raman scattering study. The Raman spectra of ...
《spray系统业界对比》 在信息技术领域,spray系统是一种广泛应用的高性能、轻量级的HTTP服务构建框架,尤其在微服务架构中备受青睐。本文将深入探讨spray系统在业界的应用情况,并与其他同类系统进行对比,以帮助...
事实证明,Spray-SPA 对我来说是一个很好的起点。 这是我决定使用 Spray 时最完整的示例之一。 但是,我觉得该项目设计更好的版本可以为人们提供更好的参考。 我几乎重写了整个后端,使项目的结构和设计进一步从简单...
它最初只支持 Web 服务,并使用 Spray 来处理 HTTP 请求/响应。 Spray Http 客户端/服务层建立在 akka IO 之上。 任何其他协议,例如 ftp、jms 或 zeromq,都将在 Akka IO 之上实现。 Akka IO 已经支持 tcp 和 udp...
spray-json 框架是 Scala 语言中的一个轻量级、高效的 JSON 处理库,主要用于解析和生成 JSON 数据。这个框架强调无侵入性,因为它不依赖于反射,而是利用类型类来实现自定义对象的序列化和反序列化。在 Scala 中,...
spray-socketio 是 spray 的扩展,实现对 Socket.io 的支持。 标签:spray
etcd是Google开源的一个分布式键值存储系统,用于在分布式环境中提供高可用性的服务发现和配置管理。这个压缩包文件"etcd-v3.5.0-linux-amd64.tar.gz"包含了etcd的v3.5.0版本,特别为Linux x86_64(AMD64)架构优化...
PIPENET TM Spray/Sprinkler Module 是 专门针对消防系统设计而开发的专业软件, 可选用的消防规范包括NFPA 和FOC 。它 可满足诸如石油、化工、钻井平台、电站 及船只等行业对消防系统的严格且特殊的 设计要求。
该项目通过文档为您自己的Spray REST api提供了一个起点。 已实现以下REST端点: 木星 火星 宠物 为每个端点宠物,火星,木星创建一个演员。 请按照以下步骤开始: git克隆这个仓库。 $ git clone git://github...