无需Java代码通过JHipster生成有安全验证的微服务应用


本教程来自baeldung,主要展示通过JHipster自动生成有安全验证的微服务应用,整个过程无需编写一行Java代码,包括Angular前端和微服务后端。以下是主要步骤翻译,更详细截图对照原文:
在本教程中,我们将探索JHipster的用户帐户和授权服务  - 简称UAA - 以及如何使用它来保护完全成熟的基于JHispter的微服务应用程序。更好的是,所有这些都可以在不编写任何代码的情况下实现!

JHipster的UAA是一个微服务,它在我们的应用程序中独立于其他服务构建,部署和运行。它用作:

  • OAuth2授权服务器,基于Spring Boot的实现
  • 身份管理服务器,公开用户帐户CRUD API

JHipster UAA还支持典型的登录功能,如自我注册和“记住我”。当然,它与其他JHipster服务完全集成。

在开始任何开发之前,需要一个正在运行的JHipster Registry注册中心,注册服务允许我们创建的不同服务来查找和相互通信。

1.生成新的JHipster UAA服务
使用JHipster命令行实用程序生成我们的UAA服务:

$ mkdir uaa
$ cd uaa
$ jhipster

这提示我们回答一些问题进行定制,第一个问题是我们想要生成哪种类型的应用程序。使用箭头键,我们将选择“JHipster UAA(用于微服务OAuth2身份验证)”选项。
接下来是应用程序名称,服务器端口和服务发现的输入。在大多数情况下,默认答案都很好。
应用程序的基本名称会影响了许多生成的工件,我们选择了“uaa”(小写) 

回答完这些问题之后,JHipster将创建所有项目文件并安装npm包依赖项(在这种情况下并不真正使用)。我们现在可以使用本地Maven脚本来构建和运行我们的UAA服务:

$ ./mvnw
... build messages omitted
2018-10-14 14:07:17.995  INFO 18052 --- [  restartedMain] com.baeldung.jhipster.uaa.UaaApp         :
----------------------------------------------------------
        Application 'uaa' is running! Access URLs:
        Local:          http://localhost:9999/
        External:       http:
//192.168.99.1:9999/
        Profile(s):     [dev, swagger]
----------------------------------------------------------
2018-10-14 14:07:18.000  INFO 18052 --- [  restartedMain] com.baeldung.jhipster.uaa.UaaApp         :
----------------------------------------------------------
        Config Server:  Connected to the JHipster Registry config server!
----------------------------------------------------------

关键信息是:Connected to the JHipster Registry config server!,这表明UAA能够自行注册,并可供其他微服务和网关发现。

2. 测试UAA服务
由于生成的UAA服务本身没有UI,因此我们必须使用直接API调用来测试它是否按预期工作。
在将其与其他部分或我们的系统一起使用之前,我们必须确保有两个功能: OAuth2令牌生成和帐户检索。
首先,让我们使用简单的  curl命令从UAA的OAuth端点获取一个新令牌:

$ curl -X POST --data \
 "username=user&password=user&grant_type=password&scope=openid" \
 http:
//web_app:changeit@localhost:9999/oauth/token

在这里,我们使用  密码授权 流程,使用两对凭证。在这种流程中,我们使用基本的HTTP身份验证发送客户端凭据,我们直接在URL中进行编码。最终用户凭据使用标准用户名和密码参数作为正文的一部分发送。我们还使用名为“user”的用户帐户,默认情况下,该帐户  在测试配置文件中可用。
假设我们已正确提供所有详细信息,我们将获得包含访问令牌和刷新令牌的答案:

{
  "access_token" : "eyJh...(token omitted)",
 
"token_type" : "bearer",
 
"refresh_token" : "eyJ...(token omitted)",
 
"expires_in" : 299,
 
"scope" : "openid",
 
"iat" : 1539650162,
 
"jti" : "8066ab12-6e5e-4330-82d5-f51df16cd70f"
}

我们现在可以使用返回的  access_token来访问帐户资源获取相关帐户的信息,该  帐户资源在UAA服务中可用:

$ curl -H "Authorization: Bearer eyJh...(access token omitted)"
 http:
//localhost:9999/api/account
{
 
"id" : 4,
 
"login" : "user",
 
"firstName" : "User",
 
"lastName" : "User",
 
"email" : "user@localhost",
 
"imageUrl" : "",
 
"activated" : true,
 
"langKey" : "en",
 
"createdBy" : "system",
 
"createdDate" : "2018-10-14T17:07:01.336Z",
 
"lastModifiedBy" : "system",
 
"lastModifiedDate" : null,
 
"authorities" : [ "ROLE_USER" ]
}

请注意,我们必须在访问令牌到期之前发出此命令。默认情况下,UAA服务发出的令牌有效期为五分钟,这对于生产来说是一个明智的价值。
我们可以通过编辑与我们运行应用程序的配置文件相对应的application-<profile>.yml 文件,修改其中的uaa.web-client-configuration.access-token-validity-in-seconds 更改有效令牌的生命周期。这个文件位于 UAA项目的src/main/resources/config目录下。

3. 生成启用UAA的网关
现在我们确信我们的UAA服务和服务注册表正在运行,让我们创建一个与之互动的生态系统。最后,我们将添加:

  • 基于Angular的前端
  • 一个微服务后端
  • 一个支持这两者的API网关

让我们从网关开始,因为它将是与UAA协商进行身份验证的服务。它将托管我们的前端应用程序并将API请求路由到其他微服务。我们将在新创建的目录中使用JHipster命令行工具:

$ mkdir gateway
$ cd gateway
$ jhipster

和以前一样,我们必须回答几个问题才能生成项目。重要的是以下内容:

  • 应用类型:  必须是“Microservices gateway/微服务网关”
  • 申请名称:这次我们将使用“gateway/网关”
  • 服务发现:选择“JHipster registry /JHipster注册表”
  • 身份验证类型: 我们必须在此处选择“Authentication with JHipster UAA server/使用JHipster UAA服务器进行身份验证”选项
  • UI框架:  让我们选择“Angular 6”

一旦JHipster生成了所有工件,我们就可以使用提供的Maven包装器脚本构建和运行网关:
$ ./mwnw
... many messages omitted
----------------------------------------------------------
        Application 'gateway' is running! Access URLs:
        Local:          http://localhost:8080/
        External:       http:
//192.168.99.1:8080/
        Profile(s):     [dev, swagger]
----------------------------------------------------------
2018-10-15 23:46:43.011  INFO 21668 --- [  restartedMain] c.baeldung.jhipster.gateway.GatewayApp   :
----------------------------------------------------------
        Config Server:  Connected to the JHipster Registry config server!
----------------------------------------------------------

将浏览器指向http://localhost:8080来访问我们的应用程序,它应显示默认生成的主页。

让我们继续登录我们的应用程序,导航到  Account> Login菜单项。我们将使用admin / admin 作为凭据,JHipster默认自动创建。一切顺利,欢迎页面将显示确认登录成功的消息:you are logged as use "admin"!

回顾一下l流程: 首先,网关将我们的凭据发送到UAA的OAuth2令牌端点,该端点验证它们并生成包含访问和刷新JWT令牌的响应。然后网关获取这些令牌并将其作为cookie发送回浏览器。

接下来,  访问/ uaa / api / account API的Angular前端,网关再次转发给UAA。在此过程中,网关获取包含访问令牌的cookie,并使用其值为请求添加授权头。
如果需要,我们可以通过检查UAA和Gateway的日志来详细了解所有这些流程。我们还可以通过将org.apache.http.wire记录器级别设置为DEBUG来获取完整的路由步骤级数据  。

4.生成支持UAA的微服务
现在我们的应用程序环境已经启动并运行,现在是时候添加一个简单的微服务了。我们将创建一个“quotes”微服务,它将公开一个完整的REST API,允许我们创建,查询,修改和删除一组股票报价。每个报价只有三个属性:

  • 报价的交易代码
  • 它的价格,和
  • 最后一笔交易的时间戳

回到我们的终端并使用JHipster的命令行工具来生成我们的项目:

$ mkdir quotes
$ cd quotes
$ jhipster

这次,我们将要求JHipster生成一个微服务应用程序,我们将其称为“quotes”。问题类似于我们之前回答的问题。我们可以保留其中大多数的默认值,除了这三个:

  • 服务发现:  选择“JHipster Registry”,因为我们已经在我们的架构中使用它
  • UAA应用程序的路径:由于我们将所有项目目录保存在同一文件夹下,这将是../uaa (当然,除非我们已经更改了它)
  • 身份验证类型:选择“JHipster UAA服务器”

一旦JHipster完成项目的生成,我们就可以继续构建它:

$ mvnw
... many, many messages omitted
----------------------------------------------------------
        Application 'quotes' is running! Access URLs:
        Local:          http://localhost:8081/
        External:       http:
//192.168.99.1:8081/
        Profile(s):     [dev, swagger]
----------------------------------------------------------
2018-10-19 00:16:05.581  INFO 16092 --- [  restartedMain] com.baeldung.jhipster.quotes.QuotesApp   :
----------------------------------------------------------
        Config Server:  Connected to the JHipster Registry config server!
----------------------------------------------------------
... more messages omitted

5. 添加报价资源
让我们使用JHipster的工具向项目添加一个实体。这次我们将使用  import-jdl命令,这将使我们免于单独提供所有细节的繁琐且容易出错的过程。有关JDL格式的其他信息,请参阅完整的JDL参考
接下来,我们创建一个名为quotes.jh的文本文件,  其中包含我们的  Quote 实体定义,以及一些代码生成指令:

entity Quote {
  symbol String required unique,
  price BigDecimal required,
  lastTrade ZonedDateTime required
}
dto Quote with mapstruct
paginate Quote with pagination
service Quote with serviceImpl
microservice Quote with quotes
filter Quote
clientRootFolder Quote with quotes

我们现在可以将此实体定义导入到我们的项目中:

$ jhipster import-jdl quotes.jh

注意:在导入期间,JHipster会在对master.xml文件应用更改时抱怨冲突  。在这种情况下,我们可以选择 overwrite  覆盖选项。

我们现在可以使用mvnw再次构建和运行我们的微服务  。 一旦启动,我们就可以验证网关是否选择了访问网关视图的新路由  ,可从“  管理”菜单中获取。这一次,我们可以看到“/ q​​uotes / **”路由有一个条目, 表明后端已准备好供UI使用。

6.添加报价UI
最后,让我们在网关项目中生成CRUD UI,我们将用它来访问我们的报价。我们将使用“quotes”微服务项目中的相同JDL文件来生成UI组件,我们将使用JHipster的import-jdl命令导入它:

$ jhipster import-jdl ../jhipster-quotes/quotes.jh
...messages omitted
? Overwrite webpack\webpack.dev.js? <b>y</b>
... messages omitted
Congratulations, JHipster execution is complete!

在导入期间,JHipster将提示几次针对冲突文件应采取的操作。在我们的例子中,我们可以简单地覆盖现有资源,因为我们还没有进行任何自定义。

现在我们可以重新启动网关,看看我们已经完成了什么。让我们将浏览器指向http://localhost:8080的网关,确保我们刷新其内容。“ 实体”菜单现在应该具有报价资源的新条目 .单击此菜单选项将显示报价列表屏幕. 该列表是空的 - 我们尚未添加任何报价!让我们尝试通过单击此屏幕右上角的“创建新引用按钮”来添加一个,这将我们带到创建/编辑表单.
作为管理员,我们还可以访问API菜单项,它将我们带到标准的Swagger API Developer Portal。在此屏幕中,我们可以选择一个可用的API进行练习:

  • default: Gateway: 显示可用的路由
  • uaa:帐户和用户API
  • quotes: 报价API

7.后续步骤
到目前为止,我们构建的应用程序按预期工作,为进一步开发提供了坚实的基础。我们绝对还需要编写一些(或很多)自定义代码,具体取决于我们要求的复杂程度。一些可能需要一些工作的领域是:

  • UI外观定制:由于前端应用程序的结构化方式,这通常很容易 - 我们可以通过简单地使用CSS并添加一些图像来实现很长的路要走
  • 用户存储库更改:某些组织已经拥有某种内部用户存储库(例如LDAP目录) - 这将需要对UAA进行更改,但不错的部分是我们只需要更改一次
  • 对实体的细粒度授权: 生成的实体后端使用的标准安全模型没有任何类型的实例级和/或字段级安全性  - 开发人员可以在适当的级别添加这些限制(API或服务,视情况而定)

即使有这些评论,使用像JHispter这样的工具在开发新应用程序时也会有很大帮助。它将带来坚实的基础,并且随着系统和开发人员的发展,我们的代码库可以保持良好的一致性。

本文中提供的项目的完整代码可以在我们的GitHub存储库中找到