深圳SEO网站建设优化,简约装修,三亚推广公司,织梦怎么制作手机网站“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕#xff1f; 尝试使用Okta API进行托管身份验证#xff0c;授权和多因素身份验证。 如果您使用Spring Boot#xff0c;Spring Cloud和Spring Cloud Config#xff0c;则… “我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕 尝试使用Okta API进行托管身份验证授权和多因素身份验证。 如果您使用Spring BootSpring Cloud和Spring Cloud Config则只需最少的代码即可构建微服务架构。 将所有内容打包到Docker容器中即可使用Docker Compose运行所有内容。 如果您在服务之间进行通信则可以通过不在docker-compose.yml文件中公开其端口来确保服务的安全性。 但是如果有人不小心暴露了微服务应用程序的端口会怎样 他们仍然安全还是任何人都可以访问他们的数据 在本文中我将向您展示如何使用HTTPS和OAuth 2.0保护服务到服务的通信。 使用Spring BootSpring Cloud和Spring Cloud Config开发微服务堆栈 我将简化使用Spring BootSpring Cloud和Spring Cloud Config构建完整的微服务堆栈的过程。 我的好友拉斐尔Raphael写了一篇文章介绍如何构建Spring微服务并将其Docker化用于生产 。 您可以使用他的示例应用程序作为起点。 克隆okta-spring-microservices-docker-example项目 git clone https://github.com/oktadeveloper/okta-spring-microservices-docker-example.git spring-microservices-security
cd spring-microservices-security 此项目在Okta上需要两个OpenID Connect应用程序一个用于开发一个用于生产。 如果没有完成上述教程则需要在Okta上创建每个应用程序。 在Okta上创建OpenID Connect应用程序 您可以注册一个免费的开发人员帐户 该帐户最多可以有0个月活跃用户费用为$ 0。 对于这个例子来说应该足够了。 为什么选择Okta 因为编写身份验证很无聊。 Okta具有身份验证和用户管理API可让您更快地开发应用。 我们的API和SDK使您可以在几分钟内轻松地进行身份验证管理和保护用户安全。 创建帐户后在Okta的信息中心“ 应用程序” “ 添加应用程序” 中创建一个新的Web应用程序 。 给应用程序起一个您将记住的名称复制现有的登录重定向URI并使其使用HTTPS。 单击完成 。 结果应类似于下面的屏幕截图。 创建另一个用于生产的应用程序。 我给我的Prod Microservices 。 在您克隆的项目中修改config/school-ui.properties以使用开发应用程序中的设置。 okta.oauth2.issuerhttps://{yourOktaDomain}/oauth2/default
okta.oauth2.clientId{devClientId}
okta.oauth2.clientSecret{devClientId} 当使用Maven单独运行应用程序时将使用这些设置。 在Docker Compose上运行时使用生产设置。 修改config-data/school-ui-production.properties以使用生产应用程序中的设置。 okta.oauth2.clientId{prodClientId}
okta.oauth2.clientSecret{prodClientId} 您可以在spring.profiles.active docker-compose.yml看到spring.profiles.active打开生产配置文件 school-ui:image: developer.okta.com/microservice-docker-school-ui:0.0.1-SNAPSHOTenvironment:- JAVA_OPTS-DEUREKA_SERVERhttp://discovery:8761/eureka-Dspring.profiles.activeproductionrestart: on-failuredepends_on:- discovery- configports:- 8080:8080 Docker Compose从应用程序上方的目录中运行并从config-data目录读取其数据。 因此您需要将这些属性文件复制到此目录中。 从该项目的根目录运行以下命令。 cp config/*.properties config-data/.使用Docker Compose启动Spring微服务堆栈 该项目在其根目录中有一个聚合器pom.xml 使您可以使用一个命令来构建所有项目。 运行以下Maven命令为每个项目构建测试和构建Docker映像。 mvn clean install 如果您尚未安装Maven则可以使用SDKMAN进行安装 sdk install maven 该过程完成后使用Docker Compose启动所有应用程序{configdiscoveryschool-service和school-ui}。 如果尚未安装请参阅安装Docker Compose 。 docker-compose up -d 您可以使用Kitematic查看每个应用程序启动时的日志。 在您喜欢的浏览器中导航到http://localhost:8080 。 完成后您应该可以登录并查看学校课程列表。 Spring Security和OAuth 2.0 此示例使用Okta的Spring Boot Starter 它是Spring Security之上的薄层。 Okta入门程序简化了配置并在访问令牌中进行了观众验证。 它还允许您指定将用于创建Spring Security授权的声明。 docker-compose.yml文件不会将school-service公开给外界。 它通过不指定ports 。 school-ui项目有一个SchoolController类该类使用Spring的RestTemplate与school-service进行RestTemplate 。 GetMapping(/classes)
PreAuthorize(hasAuthority(SCOPE_profile))
public ResponseEntityListTeachingClassDto listClasses() {return restTemplate.exchange(http://school-service/class, HttpMethod.GET, null,new ParameterizedTypeReferenceListTeachingClassDto() {});
} 您会注意到此类的端点上存在安全性但是服务之间不存在安全性。 我将在下面的步骤中向您展示如何解决该问题。 首先公开school-service的端口以模拟有人用粗俗的方式进行配置。 在docker-compose.yml更改school-service配置以公开其端口。 school-service:image: developer.okta.com/microservice-docker-school-service:0.0.1-SNAPSHOTenvironment:- JAVA_OPTS-DEUREKA_SERVERhttp://discovery:8761/eurekadepends_on:- discovery- configports:- 8081:8081 使用Docker Compose重新启动一切 docker-compose down
docker-compose up -d 您会看到不需要身份验证即可查看http://localhost:8081 。 kes 在继续下一部分之前 请确保关闭所有Docker容器。 docker-compose downHTTPS无处不在 HTTPS代表“安全” HTTP。 HTTPS连接经过加密其内容比HTTP连接难读得多。 近年来即使在开发过程中在所有地方都使用HTTPS的趋势已经发生了很大的变化。 使用HTTPS时可能会遇到一些问题因此尽早发现它们是很好的。 让我们加密是一个提供免费HTTPS证书的证书颁发机构。 它还具有用于自动续订的API。 简而言之它使HTTPS变得如此简单没有理由不使用它 有关如何将certbot与“让我们加密”一起使用以生成证书的说明请参阅将社交登录名添加到您的JHipster应用程序 。 我也鼓励您签出Spring Boot Starter ACME 。 这是一个Spring Boot模块它使用Lets Encrypt和自动证书管理环境ACME协议简化了生成证书的过程。 使用mkcert简化本地TLS 我最近发现了一个名为mkcert的工具该工具可以创建localhost证书。 您可以在macOS上使用Homebrew安装它 brew install mkcert
brew install nss # Needed for Firefox 如果您使用的是Linux则需要先安装certutil sudo apt install libnss3-tools 然后使用Linuxbrew运行brew install mkcert命令。 Windows用户可以使用Chocolately或Scoop 。 执行以下mkcert命令以为localhost 127.0.0.1 您的计算机名称和discovery主机如docker-compose.yml所引用生成证书。 mkcert -install
mkcert localhost 127.0.0.1 ::1 hostname discovery 如果这样生成的文件中带有数字请重命名文件使其没有数字。 mv localhost2.pem localhost.pem
mv localhost2-key.pem localhost-key.pem使用Spring Boot的HTTPS Spring Boot不支持带有PEM扩展名的证书但是您可以将其转换为Spring Boot支持的PKCS12扩展名。 您可以使用OpenSSL将证书和私钥转换为PKCS12。 这对于“加密我们生成的证书”也是必要的。 运行openssl转换证书 openssl pkcs12 -export -in localhost.pem -inkey \
localhost-key.pem -out keystore.p12 -name bootifulsecurity 在出现提示时指定密码。 在项目的根目录中创建一个https.env文件并指定以下属性以启用HTTPS。 export SERVER_SSL_ENABLEDtrue
export SERVER_SSL_KEY_STORE../keystore.p12
export SERVER_SSL_KEY_STORE_PASSWORD{yourPassword}
export SERVER_SSL_KEY_ALIASbootifulsecurity
export SERVER_SSL_KEY_STORE_TYPEPKCS12 更新.gitignore文件以排除.env文件以便密钥库密码不会最终出现在源代码管理中。 *.env 运行source https.env来设置这些环境变量。 或者甚至更好的方法是将其添加到.bashrc或.zshrc文件中以便为每个新Shell设置这些变量。 是的您也可以将它们包含在每个应用程序的application.properties 但随后会将机密存储在源代码管理中。 如果您没有将此示例检入源代码管理则可以复制/粘贴以下设置。 server.ssl.enabledtrue
server.ssl.key-store../keystore.p12
server.ssl.key-store-password: {yourPassword}
server.ssl.key-store-type: PKCS12
server.ssl.key-alias: bootifulsecurity 启动discovery应用程序 cd discovery
source ../https.env
mvn spring-boot:run 然后确认您可以通过https://localhost:8761访问它。 打开docker-compose.yml并将http所有实例更改为https 。 编辑school-ui/src/main/java/…/ui/controller/SchoolController.java以将对school-service的调用更改为使用HTTPS。 return restTemplate.exchange(https://school-service/class, HttpMethod.GET, null,new ParameterizedTypeReferenceListTeachingClassDto() {}); 更新{config,school-service,school-ui}/src/main/resources/application.properties以添加使每个实例注册为安全应用程序的属性。 eureka.instance.secure-port-enabledtrue
eureka.instance.secure-port${server.port}
eureka.instance.status-page-urlhttps://${eureka.hostname}:${server.port}/actuator/info
eureka.instance.health-check-urlhttps://${eureka.hostname}:${server.port}/actuator/health
eureka.instance.home-page-urlhttps://${eureka.hostname}${server.port}/ 另外将每个application.properties 和bootstrap.yml 的Eureka地址更改为https://localhost:8761/eureka 。 school-ui项目中的application.properties没有指定端口。 您需要添加server.port8080 。 此时您应该能够通过在每个项目中在单独的终端窗口中运行以下命令来启动所有应用程序。 source ../https.env
./mvnw spring-boot:start 在https://localhost:8080确认所有工作正常。 然后使用killall java杀死所有内容。 结合使用HTTPS和Docker Compose Docker不读取环境变量也不了解您的本地CA证书颁发机构并且您不能将父目录中的文件添加到映像中。 要解决此问题您需要将keystore.p12和localhost.pem复制到每个项目的目录中。 第一个将用于Spring Boot第二个将被添加到每个映像上的Java Keystore中。 cp localhost.pem keystore.p12 config/.
cp localhost.pem keystore.p12 discovery/.
cp localhost.pem keystore.p12 school-service/.
cp localhost.pem keystore.p12 school-ui/. 然后修改每个项目的Dockerfile以复制证书并将其添加到其信任存储中。 FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/*.jar app.jar
ADD keystore.p12 keystore.p12
USER root
COPY localhost.pem $JAVA_HOME/jre/lib/security
RUN \cd $JAVA_HOME/jre/lib/security \ keytool -keystore cacerts -storepass changeit -noprompt \-trustcacerts -importcert -alias bootifulsecurity -file localhost.pem
ENV JAVA_OPTS
ENTRYPOINT [ sh, -c, java $JAVA_OPTS -Djava.security.egdfile:/dev/./urandom -jar /app.jar ] 然后使用Spring Boot和HTTPS的环境变量创建一个.env文件。 SERVER_SSL_ENABLEDtrue
SERVER_SSL_KEY_STOREkeystore.p12
SERVER_SSL_KEY_STORE_PASSWORD{yourPassword}
SERVER_SSL_KEY_ALIASbootifulsecurity
SERVER_SSL_KEY_STORE_TYPEPKCS12
EUREKA_INSTANCE_HOSTNAME{yourHostname} 您可以通过运行hostname来获取{yourHostname}的值。 Docker Compose具有一个“ env_file”配置选项允许您读取此文件以获取环境变量。 更新docker-compose.yml以为每个应用程序指定一个env_file 。 version: 3
services:discovery:env_file:- .env...config:env_file:- .env...school-service:env_file:- .env...school-ui:env_file:- .env... 您可以通过从根目录运行docker-compose config来确保其正常工作。 运行mvn clean install以启用Eureka注册启用HTTPS来重建所有Docker映像。 然后开始一切。 docker-compose up -d 现在您的所有应用程序都在带有HTTPS的Docker中运行 在https://localhost:8080证明。 如果您的应用程序无法启动或无法彼此通信请确保您的主机名与.env主机名匹配。 您可以进一步提高安全性使用OAuth 2.0保护您的学校服务API。 OAuth 2.0的API安全性 将Okta Spring Boot Starter和Spring Cloud Config添加到school-service/pom.xml dependencygroupIdcom.okta.spring/groupIdartifactIdokta-spring-boot-starter/artifactIdversion1.1.0/version
/dependency
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactId
/dependency 然后在school-service/src/main/java/…/service/configuration创建一个SecurityConfiguration.java类 package com.okta.developer.docker_microservices.service.configuration;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().oauth2ResourceServer().jwt();}
} 创建一个school-service/src/test/resources/test.properties文件并添加属性以便Okta的配置通过并且在测试时不使用发现或配置服务器。 okta.oauth2.issuerhttps://{yourOktaDomain}/oauth2/default
okta.oauth2.clientIdTEST
spring.cloud.discovery.enabledfalse
spring.cloud.config.discovery.enabledfalse
spring.cloud.config.enabledfalse 然后修改ServiceApplicationTests.java以加载此文件以用于测试属性 import org.springframework.test.context.TestPropertySource;...
TestPropertySource(locationsclasspath:test.properties)
public class ServiceApplicationTests {...
} 添加school-service/src/main/resources/bootstrap.yml文件该文件允许该实例从Spring Cloud Config中读取其配置。 eureka:client:serviceUrl:defaultZone: ${EUREKA_SERVER:https://localhost:8761/eureka}
spring:application:name: school-servicecloud:config:discovery:enabled: trueserviceId: CONFIGSERVERfailFast: true 然后复制config/school-ui.properties以具有等效的school-service 。 cp config/school-ui.properties config/school-service.properties 对于Docker Compose您还需要使用以下设置创建config-data/school-service.properties okta.oauth2.issuerhttps://{yourOktaDomain}/oauth2/default
okta.oauth2.clientId{prodClientId}
okta.oauth2.clientSecret{prodClientId} 您还需要修改docker-compose.yml以便在失败时重新启动school-service 。 school-service:...restart: on-failure 您可以在Okta上创建一个使用客户端凭据的服务应用程序但是这篇文章已经足够复杂了。 有关该方法的更多信息请参阅使用Spring Boot和OAuth 2.0进行安全的服务器到服务器通信 。 您需要做的最后一步是修改SchoolController 在school-ui项目中以向其对school-server的请求中添加OAuth 2.0访问令牌。 例子1.向RestTemplate添加一个AccessToken package com.okta.developer.docker_microservices.ui.controller;import com.okta.developer.docker_microservices.ui.dto.TeachingClassDto;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;import java.io.IOException;
import java.util.List;Controller
RequestMapping(/)
public class SchoolController {private final OAuth2AuthorizedClientService authorizedClientService;private final RestTemplate restTemplate;public SchoolController(OAuth2AuthorizedClientService clientService,RestTemplate restTemplate) { (1)this.authorizedClientService clientService;this.restTemplate restTemplate;}RequestMapping()public ModelAndView index() {return new ModelAndView(index);}GetMapping(/classes)PreAuthorize(hasAuthority(SCOPE_profile))public ResponseEntityListTeachingClassDto listClasses(AuthenticationPrincipal OAuth2AuthenticationToken authentication) { (2)OAuth2AuthorizedClient authorizedClient this.authorizedClientService.loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(),authentication.getName()); (3)OAuth2AccessToken accessToken authorizedClient.getAccessToken(); (4)restTemplate.getInterceptors().add(getBearerTokenInterceptor(accessToken.getTokenValue())); (5)return restTemplate.exchange(https://school-service/class, HttpMethod.GET, null,new ParameterizedTypeReferenceListTeachingClassDto() {});}private ClientHttpRequestInterceptor getBearerTokenInterceptor(String accessToken) {return (request, bytes, execution) - {request.getHeaders().add(Authorization, Bearer accessToken);return execution.execute(request, bytes);};}
} 将OAuth2AuthorizedClientService依赖项添加到构造函数 将OAuth2AuthenticationToken注入listClasses()方法 从authentication创建OAuth2AuthorizedClient 从授权客户端获取访问令牌 将访问令牌添加到Authorization标头中 而已 由于school-ui和school-service使用相同的OIDC应用程序设置因此服务器将识别并验证访问令牌也是JWT并允许访问。 此时您可以选择使用./mvnw spring-boot:run或Docker Compose单独运行所有应用程序。 后一种方法只需要几个命令。 mvn clean install
docker-compose down
docker-compose up -d使用HTTP Basic Auth与Eureka和Spring Cloud Config进行安全的微服务通信 为了进一步提高微服务Eureka Server和Spring Cloud Config之间的安全性您可以添加HTTP基本身份验证。 为此您需要在config和discovery项目中都添加spring-boot-starter-security作为依赖项。 然后您需要为每个参数指定一个spring.security.user.password并对其进行加密。 您可以在Spring Cloud Config的安全性文档中了解有关如何执行此操作的更多信息。 在两个项目中都配置了Spring Security之后就可以调整URL以在其中包含用户名和密码。 例如以下是在school-ui项目的bootstrap.yml eureka:client:serviceUrl:defaultZone: ${EUREKA_SERVER:https://username:passwordlocalhost:8761/eureka} 您需要对docker-compose.yml的URL进行类似的调整。 增强您对Spring微服务Docker和OAuth 2.0的了解 本教程向您展示了如何确保微服务体系结构中的服务到服务通信是安全的。 您学习了如何在所有地方使用HTTPS以及如何使用OAuth 2.0和JWT锁定API。 您可以在oktadeveloper / okta-spring-microservices-https-example上的GitHub上找到此示例的源代码。 如果您想进一步探讨这些主题我想您会喜欢以下博客文章 构建Spring微服务并对其进行Dockerize生产 使用Spring Boot为Microbrews构建微服务架构 使用Spring Boot 2.0和OAuth 2.0构建并保护微服务 使用OAuth 2.0和JHipster开发微服务架构 使用Spring Boot和OAuth 2.0进行安全的服务器到服务器通信 这些博客文章有助于使本文中的所有内容都能正常工作 使用Spring Cloud Netflix Eureka进行安全发现 让我们加密保护的Spring Boot 有问题吗 在下面的评论中询问他们 如果您的问题与这篇文章无关请将其发布到我们的开发者论坛 。 要获取有关更多技术博客文章的通知 请在Twitter上关注我们oktadev或订阅我们的YouTube频道 。 “具有HTTPS和OAuth 2.0的安全的服务到服务的Spring微服务”最初于2019年3月7日发布在Okta开发者博客上。 “我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕 尝试使用Okta API进行托管身份验证授权和多因素身份验证。 翻译自: https://www.javacodegeeks.com/2019/03/secure-service-spring-microservices.html