设为首页 加入收藏

TOP

restapi(0)- 平台数据维护,写在前面(一)
2019-08-15 00:10:42 】 浏览:109
Tags:restapi 平台 数据 维护 前面

   在云计算的推动下,软件系统发展趋于平台化。云平台系统一般都是分布式的集群系统,采用大数据技术。在这方面akka提供了比较完整的开发技术支持。我在上一个系列有关CQRS的博客中按照实际应用的要求对akka的一些开发技术进行了介绍。CQRS模式着重操作流程控制,主要涉及交易数据的管理。那么,作为交易数据产生过程中发挥验证作用的一系列基础数据如用户信息、商品信息、支付类型信息等又应该怎样维护呢?首先基础数据也应该是在平台水平上的,但数据的采集、维护是在系统前端的,比如一些web界面。所以平台基础数据维护系统是一套前后台结合的系统。对于一个开放的平台系统来说,应该能够适应各式各样的前端系统。一般来讲,平台通过定义一套api与前端系统集成是通用的方法。这套api必须遵循行业标准,技术要普及通用,这样才能支持各种异类前端系统功能开发。在这些要求背景下,相对gRPC, GraphQL来说,REST风格的http集成模式能得到更多开发人员的接受。

  在有关CQRS系列博客里,我以akka-http作为系统集成工具的一种,零星地针对实际需要对http通信进行了介绍。在restapi这个系列里我想系统化的用akka-http构建一套完整的,REST风格数据维护和数据交换api,除CRUD之外还包括网络安全,文件交换等功能。我的计划是用akka-http搭建一个平台数据维护api的REST-CRUD框架,包含所有标配功能如用户验证、异常处理等。CRUD部分要尽量做成通用的generic,框架型的,能用一套标准的方法对任何数据表进行操作。

akka-http是一套http程序开发工具。它的Routing-DSL及数据序列化marshalling等都功能强大。特别是HttpResponse处理,一句complete解决了一大堆问题,magnet-pattern结合marshalling让它的使用更加方便。

在这篇讨论里先搭一个restapi的基本框架,包括客户端身份验证和使用权限。主要是示范如何达到通用框架的目的。这个在akka-http编程里主要体现在Routing-DSL的结构上,要求Route能够简洁易懂,如下:

  val route = path("auth") { authenticateBasic(realm = "auth", authenticator.getUserInfo) { userinfo => post { complete(authenticator.issueJwt(userinfo))} } } ~ pathPrefix("api") { authenticateOAuth2(realm = "api", authenticator.authenticateToken) { validToken => (path("hello") & get) { complete(s"Hello! userinfo = ${authenticator.getUserInfo(validToken)}") } ~ (path("how are you") & get) { complete(s"Hello! userinfo = ${authenticator.getUserInfo(validToken)}") } // ~ ...
 } }

我觉着这应该是框架型正确的方向:把所有功能都放在api下,统统经过权限验证。可以直接在后面不断加功能Route。

身份验证和使用权限也应该是一套标准的东西,但身份验证方法可能有所不同,特别是用户身份验证可能是通过独立的身份验证服务器实现的,对不同的验证机制应该有针对性的定制函数。构建身份管理的对象应该很方便或者很通用,如下:

  val authenticator = new AuthBase() .withAlgorithm(JwtAlgorithm.HS256) .withSecretKey("OpenSesame") .withUserFunc(getValidUser)

AuthBase源码如下:

package com.datatech.restapi import akka.http.scaladsl.server.directives.Credentials import pdi.jwt._ import org.json4s.native.Json import org.json4s._ import org.json4s.jackson.JsonMethods._ import pdi.jwt.algorithms._ import scala.util._ object AuthBase { type UserInfo = Map[String, Any] case class AuthBase( algorithm: JwtAlgorithm = JwtAlgorithm.HMD5, secret: String = "OpenSesame", getUserInfo: Credentials => Option[UserInfo] = null) { ctx => def withAlgorithm(algo: JwtAlgorithm): AuthBase = ctx.copy(algorithm=algo) def withSecretKey(key: String): AuthBase = ctx.copy(secret = key) def withUserFunc(f: Credentials => Option[UserInfo]): AuthBase = ctx.copy(getUserInfo = f) def authenticateToken(credentials: Credentials): Option[String] = credentials match { case Credentials.Provided(token) => algorithm match { case algo: JwtAsymmetricAlgorithm => Jwt.isValid(token, secret, Seq((algorithm.asInstanceOf[JwtAsymmetricAlgorithm]))) match { case true => Some(token) case _ => None } case _ => Jwt.isValid(token, secret, Seq((algorithm.asInstanceOf[JwtHmacAlgorithm]))) match { case true => Some(token) case _ => None } } case _ => None } def getUserInfo(token: String): Option[UserInfo] = { algorithm match { case algo: JwtAsymmetricAlgorithm => Jwt.decodeRawAll(token, secret, Seq(algorithm.asInstanceOf[JwtAsymmetric
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Akka-CQRS(14)- Http标准安全解.. 下一篇Akka-CQRS(16)- gRPC用JWT进行..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目