国内购物网站大全,网站建设与客户价格谈判技巧,《网站建设》期末考试,北京正邦设计公司官网朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户#xff1f; 立即尝试Okta的API和Java SDK。 在几分钟之内即可对任何应用程序中的用户进行身份验证#xff0c;管理和保护。 Java是开发微服务架构时使用的一种很棒的语言。 实际上#xff0c;我们行业中的一些知名人士… 朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户 立即尝试Okta的API和Java SDK。 在几分钟之内即可对任何应用程序中的用户进行身份验证管理和保护。 Java是开发微服务架构时使用的一种很棒的语言。 实际上我们行业中的一些知名人士都在使用它。 您是否听说过NetflixAmazon或Google 那eBayTwitter和LinkedIn呢 是的处理不可思议流量的主要公司正在使用Java来实现。 在Java中实现微服务架构并不适合每个人。 因此通常不需要实现微服务。 大多数公司这样做都是为了扩展人员而不是系统。 如果要扩大人员规模雇用Java开发人员是做到这一点的最佳方法之一。 毕竟比起其他大多数语言流利的Java开发人员更多-尽管JavaScript似乎正在Swift赶上来 Java生态系统具有一些完善的模式来开发微服务架构。 如果您熟悉Spring则可以在家中使用Spring Boot和Spring Cloud进行开发。 由于这是上手最快的方法之一所以我认为我将带您快速入门。 使用Spring Cloud和Spring Boot创建Java微服务 在我的大多数教程中我向您展示了如何从头开始构建所有内容。 今天我想采用一种不同的方法并与您一起完成一个预先构建的示例。 希望这会更短并且更容易理解。 您可以从克隆 oktadeveloper / java-microservices-examples存储库开始。 git clone https://github.com/oktadeveloper/java-microservices-examples.git
cd java-microservices-examples/spring-bootcloud 在spring-bootcloud目录中有三个项目 Discovery-service Netflix Eureka服务器用于服务发现。 car-service 一个简单的Car Service使用Spring Data REST来提供汽车的REST API。 api-gateway 具有/cool-cars端点的API网关该端点与car-service进行对话并过滤出不凉爽的汽车当然在我看来。 我使用start.spring.io的 REST API和HTTPie创建了所有这些应用程序。 http https://start.spring.io/starter.zip javaVersion11 \artifactIddiscovery-service nameeureka-service \dependenciescloud-eureka-server baseDirdiscovery-service | tar -xzvf -http https://start.spring.io/starter.zip \artifactIdcar-service namecar-service baseDircar-service \dependenciesactuator,cloud-eureka,data-jpa,h2,data-rest,web,devtools,lombok | tar -xzvf -http https://start.spring.io/starter.zip \artifactIdapi-gateway nameapi-gateway baseDirapi-gateway \dependenciescloud-eureka,cloud-feign,data-rest,web,cloud-hystrix,lombok | tar -xzvf -带有Java 11的Spring Microservices 为了使discovery-service在Java 11上运行我必须添加对JAXB的依赖 dependencygroupIdorg.glassfish.jaxb/groupIdartifactIdjaxb-runtime/artifactId
/dependency 其他两个应用程序可以在Java 11上开箱即用地正常运行而无需更改依赖项。 Netflix Eureka的Java服务发现 discovery-service的配置与大多数Eureka服务器相同。 它在其主类和设置其端口并关闭发现的属性上作为EnableEurekaServer批注。 server.port8761
eureka.client.register-with-eurekafalse car-service和api-gateway项目以类似的方式配置。 两者都定义了唯一的名称并且car-service配置为在端口8090上运行因此它与8080不冲突。 汽车服务/src/main/resources/application.properties server.port8090
spring.application.namecar-service api-gateway / src / main / resources / application.properties spring.application.nameapi-gateway 两个项目中的主类都使用EnableDiscoveryClient注释。 使用Spring Data REST构建Java微服务 car-service提供了REST API可让您CRUD创建读取更新和删除汽车。 当应用程序使用ApplicationRunner bean加载时它将创建一组默认的汽车。 car-service / src / main / java / com / example / carservice / CarServiceApplication.java package com.example.carservice;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.stream.Stream;EnableDiscoveryClient
SpringBootApplication
public class CarServiceApplication {public static void main(String[] args) {SpringApplication.run(CarServiceApplication.class, args);}BeanApplicationRunner init(CarRepository repository) {return args - {Stream.of(Ferrari, Jaguar, Porsche, Lamborghini, Bugatti,AMC Gremlin, Triumph Stag, Ford Pinto, Yugo GV).forEach(name - {repository.save(new Car(name));});repository.findAll().forEach(System.out::println);};}
}Data
NoArgsConstructor
Entity
class Car {public Car(String name) {this.name name;}IdGeneratedValueprivate Long id;NonNullprivate String name;
}RepositoryRestResource
interface CarRepository extends JpaRepositoryCar, Long {
}API网关中的Spring Cloud Feign和Hystrix Feign使编写Java HTTP客户端更加容易。 Spring Cloud使得仅需几行代码即可创建Feign客户端。 Hystrix可以为您的Feign客户端添加故障转移功能从而使它们更具弹性。 api-gateway使用Feign和Hystrix与下游car-service并在不可用时故障转移到fallback()方法。 它还公开了一个/cool-cars终结点该终结点过滤掉了您可能不想拥有的汽车。 api-gateway / src / main / java / com / example / apigateway / ApiGatewayApplication.java package com.example.apigateway;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.Data;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.hateoas.Resources;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.Collection;
import java.util.stream.Collectors;EnableFeignClients
EnableCircuitBreaker
EnableDiscoveryClient
EnableZuulProxy
SpringBootApplication
public class ApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(ApiGatewayApplication.class, args);}
}Data
class Car {private String name;
}FeignClient(car-service)
interface CarClient {GetMapping(/cars)CrossOriginResourcesCar readCars();
}RestController
class CoolCarController {private final CarClient carClient;public CoolCarController(CarClient carClient) {this.carClient carClient;}private CollectionCar fallback() {return new ArrayList();}GetMapping(/cool-cars)CrossOriginHystrixCommand(fallbackMethod fallback)public CollectionCar goodCars() {return carClient.readCars().getContent().stream().filter(this::isCool).collect(Collectors.toList());}private boolean isCool(Car car) {return !car.getName().equals(AMC Gremlin) !car.getName().equals(Triumph Stag) !car.getName().equals(Ford Pinto) !car.getName().equals(Yugo GV);}
}运行Java微服务架构 如果您在单独的终端窗口中使用./mvnw运行所有这些服务 ./mvnw可以导航至http://localhost:8761并查看它们是否已在Eureka中注册。 如果您在浏览器中导航到http://localhost:8080/cool-bars 您将被重定向到Okta。 什么啊 使用OAuth 2.0和OIDC保护Java微服务 我已经使用OAuth 2.0和OIDC在此微服务架构中配置了安全性。 两者有什么区别 OIDC是提供身份的OAuth 2.0的扩展。 它还提供发现功能因此可以从单个URL称为issuer 发现所有不同的OAuth 2.0端点。 如何为所有这些微服务配置安全性 我很高兴你问 我在api-gateway和car-service的pom.xml中添加了Okta的Spring Boot启动器 dependencygroupIdcom.okta.spring/groupIdartifactIdokta-spring-boot-starter/artifactIdversion1.2.0/version
/dependency 然后我在Okta创建了一个新的OIDC应用并配置了授权代码流。 如果要查看运行中的所有内容则需要完成以下步骤。 在Okta中创建Web应用程序 登录到您的1563开发者帐户或者注册 如果你没有一个帐户。 在“ 应用程序”页面上选择添加应用程序 。 在“创建新应用程序”页面上选择“ Web” 。 为您的应用提供一个令人难忘的名称将http://localhost:8080/login/oauth2/code/okta为登录重定向URI选择刷新令牌 除了授权代码 然后点击完成 。 将发行者位于API 授权服务器下 客户端ID和客户端密钥复制到两个项目的application.properties中。 okta.oauth2.issuer$issuer
okta.oauth2.client-id$clientId
okta.oauth2.client-secret$clientSecret 下一节中的Java代码已经存在但是我认为我已经对其进行了解释以便您了解正在发生的事情。 为OAuth 2.0登录和资源服务器配置Spring Security 在ApiGatewayApplication.java 我添加了Spring Security配置以启用OAuth 2.0登录并将网关作为资源服务器。 Configuration
static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {// formatter:offhttp.authorizeRequests().anyRequest().authenticated().and().oauth2Login().and().oauth2ResourceServer().jwt();// formatter:on}
} 在此示例中未使用资源服务器配置但是我添加了它以防您想将移动应用程序或SPA连接到此网关。 如果您使用的是SPA则还需要添加一个bean来配置CORS。 Bean
public FilterRegistrationBeanCorsFilter simpleCorsFilter() {UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();CorsConfiguration config new CorsConfiguration();config.setAllowCredentials(true);config.setAllowedOrigins(Collections.singletonList(*));config.setAllowedMethods(Collections.singletonList(*));config.setAllowedHeaders(Collections.singletonList(*));source.registerCorsConfiguration(/**, config);FilterRegistrationBeanCorsFilter bean new FilterRegistrationBean(new CorsFilter(source));bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;
} 如果确实使用像这样的CORS过滤器建议您将源方法和标头更改为更具体以提高安全性。 CarServiceApplication.java仅配置为资源服务器因为不希望直接访问它。 Configuration
static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {// formatter:offhttp.authorizeRequests().anyRequest().authenticated().and().oauth2ResourceServer().jwt();// formatter:on}
} 为了使API网关能够访问Car Service我在API网关项目中创建了UserFeignClientInterceptor.java 。 api-gateway / src / main / java / com / example / apigateway / UserFeignClientInterceptor.java package com.example.apigateway;import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
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.Component;Component
public class UserFeignClientInterceptor implements RequestInterceptor {private static final String AUTHORIZATION_HEADER Authorization;private static final String BEARER_TOKEN_TYPE Bearer;private final OAuth2AuthorizedClientService clientService;public UserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {this.clientService clientService;}Overridepublic void apply(RequestTemplate template) {Authentication authentication SecurityContextHolder.getContext().getAuthentication();OAuth2AuthenticationToken oauthToken (OAuth2AuthenticationToken) authentication;OAuth2AuthorizedClient client clientService.loadAuthorizedClient(oauthToken.getAuthorizedClientRegistrationId(),oauthToken.getName());OAuth2AccessToken accessToken client.getAccessToken();template.header(AUTHORIZATION_HEADER, String.format(%s %s, BEARER_TOKEN_TYPE, accessToken.getTokenValue()));}
} 我在ApiGatewayApplication.java其配置为RequestInterceptor Bean
public RequestInterceptor getUserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {return new UserFeignClientInterceptor(clientService);
} 并且我在api-gateway/src/main/resources/application.properties添加了两个属性因此Feign支持Spring Security。 feign.hystrix.enabledtrue
hystrix.shareSecurityContexttrue请参阅在启用安全性的情况下运行的Java微服务 使用./mvnw在单独的终端窗口中运行所有应用程序或者根据需要在您的IDE中运行。 为了简化在IDE中的运行根目录中有一个聚合器pom.xml 。 如果安装了IntelliJ IDEA的命令行启动器 idea pom.xml需要运行idea pom.xml 。 导航到http://localhost:8080/cool-cars 您将被重定向到Okta进行登录。 输入您的Okta开发人员帐户的用户名和密码您应该会看到凉爽的汽车清单。 如果您到此为止并成功运行了示例应用程序那么恭喜 你真酷 使用Netflix Zuul和Spring Cloud代理路由 Netflix Zuul是您可能希望在微服务体系结构中使用的另一个便捷功能。 Zuul是一项网关服务可提供动态路由监视弹性等。 为了添加Zuul我将其作为依赖项添加到api-gateway/pom.xml dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-zuul/artifactId
/dependency 然后我将EnableZuulProxy添加到ApiGatewayApplication类。 import org.springframework.cloud.netflix.zuul.EnableZuulProxy;EnableZuulProxy
SpringBootApplication
public class ApiGatewayApplication {...
} 为了将访问令牌传递到代理路由我创建了一个AuthorizationHeaderFilter类该类扩展了ZuulFilter 。 package com.example.apigateway;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.core.Ordered;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
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.security.oauth2.core.oidc.OidcUserInfo;import java.util.Optional;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;public class AuthorizationHeaderFilter extends ZuulFilter {private final OAuth2AuthorizedClientService clientService;public AuthorizationHeaderFilter(OAuth2AuthorizedClientService clientService) {this.clientService clientService;}Overridepublic String filterType() {return PRE_TYPE;}Overridepublic int filterOrder() {return Ordered.LOWEST_PRECEDENCE;}Overridepublic boolean shouldFilter() {return true;}Overridepublic Object run() {RequestContext ctx RequestContext.getCurrentContext();OptionalString authorizationHeader getAuthorizationHeader();authorizationHeader.ifPresent(s - ctx.addZuulRequestHeader(Authorization, s));return null;}private OptionalString getAuthorizationHeader() {Authentication authentication SecurityContextHolder.getContext().getAuthentication();OAuth2AuthenticationToken oauthToken (OAuth2AuthenticationToken) authentication;OAuth2AuthorizedClient client clientService.loadAuthorizedClient(oauthToken.getAuthorizedClientRegistrationId(),oauthToken.getName());OAuth2AccessToken accessToken client.getAccessToken();if (accessToken null) {return Optional.empty();} else {String tokenType accessToken.getTokenType().getValue();String authorizationHeaderValue String.format(%s %s, tokenType, accessToken.getTokenValue());return Optional.of(authorizationHeaderValue);}}
} 您可能会注意到 getAuthorizationHeader()方法中的代码与UserFeignClientInterceptor的代码非常相似。 由于只有几行因此我选择不将其移至实用程序类。 Feign拦截器用于FeignClient 而Zuul过滤器用于Zuul代理的请求。 为了使Spring Boot和Zuul知道此过滤器我在主应用程序类中将其注册为Bean。 public AuthorizationHeaderFilter authHeaderFilter(OAuth2AuthorizedClientService clientService) {return new AuthorizationHeaderFilter(clientService);
} 为了将请求从API网关代理到汽车服务我添加了到api-gateway/src/main/resources/application.properties路由。 zuul.routes.car-service.path/cars
zuul.routes.car-service.urlhttp://localhost:8090zuul.routes.home.path/home
zuul.routes.home.urlhttp://localhost:8090zuul.sensitive-headersCookie,Set-Cookie 我在/home路线的car-service项目中添加了HomeController 。 package com.example.carservice;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.security.Principal;RestController
public class HomeController {private final static Logger log LoggerFactory.getLogger(HomeController.class);GetMapping(/home)public String howdy(Principal principal) {String username principal.getName();JwtAuthenticationToken token (JwtAuthenticationToken) principal;log.info(claims: token.getTokenAttributes());return Hello, username;}
}确认您的Zuul路线工作 由于这些更改已经在您克隆的项目中因此您应该能够在浏览器中查看https://localhost:8080/cars和http://localhost:8080/home 。 Spring Cloud Config呢 在此示例中您可能已经注意到的一件事是您必须在每个应用程序中配置OIDC属性。 如果您有500个微服务这可能是一个真正的痛苦。 是的您可以将它们定义为环境变量这样就可以解决问题。 但是如果您具有使用不同OIDC客户端ID的不同微服务堆栈则此方法将很困难。 Spring Cloud Config是一个为分布式系统提供外部化配置的项目。 与其在本示例中添加它不如在以后的教程中介绍它。 那Kotlin呢 我用Java写这篇文章是因为它是Java生态系统中最受欢迎的语言。 然而根据RedMonk从2019年1月开始的编程语言排名 Kotlin呈上升趋势 。 至少在本季度Kotlin大幅增长而所有三个基于JVM的同行均下降。 实际上Kotlin跳了这么远以至于它最终进入了第20名的前20名并在此同时超越了Clojure24和Groovy24。 它仍然远远落后于Scala13但在这些排名的历史上Kotlin的增长仅次于Swift因此很有趣的发现下一轮还是接下来的比赛。 Spring对Kotlin有很好的支持您可以在start.spring.io上选择它作为语言。 如果您希望我们使用Kotlin写更多帖子请在评论中告诉我们 刷新令牌的已知问题 默认情况下Okta的访问令牌在一小时后过期。 这是预期的并且在使用OAuth 2.0时建议使用短期访问令牌。 刷新令牌的寿命通常更长思考几天或几个月并且可用于获取新的访问令牌。 使用Okta的Spring Boot启动器时这应该会自动发生但事实并非如此。 我配置了Okta组织使其访问令牌在五分钟内到期。 您可以通过以下方法执行此操作转到“ API” “ 授权服务器” “ 访问策略” 单击“ 默认策略” 然后编辑其规则。 然后将访问令牌的生存期从1小时更改为5分钟。 在浏览器中点击http://localhost:8080/cool-cars 您将被重定向到Okta进行登录。 登录后您应该会看到汽车的JSON字符串。 去做其他事情超过5分钟。 回来刷新浏览器您会看到[]而不是所有的汽车。 我仍在努力解决此问题一旦找到我将更新此帖子。 如果您碰巧知道解决方案请告诉我 更新 Spring Security 5.1尚未自动刷新OAuth访问令牌。 它应该在Spring Security 5.2中可用 。 通过Spring BootSpring Cloud和微服务获得更多乐趣 我希望您喜欢这个关于如何使用Spring Boot和Spring Cloud构建Java微服务架构的教程。 您学习了如何以最少的代码构建所有内容然后使用Spring SecurityOAuth 2.0和Okta将其配置为安全。 您可以在GitHub上找到本教程中显示的所有代码。 我们是此博客上的Spring BootSpring Cloud和微服务的忠实拥护者。 这是您可能会发现有趣的其他几篇文章 带有Spring Cloud Config和JHipster的Java微服务 Angular 8 Spring Boot 2.2立即构建一个CRUD应用程序 Spring Boot登录选项快速指南 使用Spring Boot和Kubernetes构建微服务架构 使用HTTPS和OAuth 2.0保护服务到服务的Spring微服务 构建Spring微服务并对其进行Dockerize生产 请在Twitter oktadev上关注我们并订阅我们的YouTube频道以了解更多有关Spring Boot和微服务的知识。 “带有Spring Boot和Spring Cloud的Java微服务”最初于2019年5月22日发布在Okta开发者博客上 朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户 立即尝试Okta的API和Java SDK。 在几分钟之内即可对任何应用程序中的用户进行身份验证管理和保护。 翻译自: https://www.javacodegeeks.com/2019/06/java-microservices-spring-boot-spring-cloud.html