springcolud demo(亲自搭建)
创建 一个简单的demo。整合几个基本的组件:
注册中心:Spring Cloud Netflix
配置中心:Spring Cloud Config
鉴权中心:Spring Cloud OAuth2
hystrix、feign、Zuul、Eureka等。
所有工程的都事项了负载。
写作不容易,盗版必究
总的依赖控制 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wxd.springcloud</groupId>
<artifactId>spring-cloud-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>cloud-register</module>
<module>cloud-producer</module>
<module>cloud-consumer</module>
<module>cloud-gateway</module>
<module>cloud-config-server</module>
<module>cloud-config-client</module>
<module>cloud-OAuth2-server</module>
<module>cloud-OAuth2-client</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
<properties>
<project.build.sourceencoding>UTF-8</project.build.sourceencoding>
<project.reporting.outputencoding>UTF-8</project.reporting.outputencoding>
<java.version>1.8</java.version>
<swagger.version>2.6.0</swagger.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
一 创建注册中心
- 访问注册中心的地址 http://localhost:8081/
如图:demo.jpg
- pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- yml
server:
port: 8081
spring:
application:
name: eureka-server
eureka:
client:
# 表示是否将自己注册到Eureka Server,默认为true。
registerWithEureka: false
# 表示是否从Eureka Server获取注册信息,默认为true。
fetchRegistry: false
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8761/eureka ;多个地址可使用,分隔
serviceUrl:
defaultZone: http://localhost:${server.port}/eureka/
- 启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class RegisterApp { public static void main(String[] args) { SpringApplication.run(RegisterApp.class, args); } }
- 集群搭建参考
https://blog.****.net/maoyeqiu/article/details/78554196主要配置如下
#server1 spring.application.name=eureka-server server.port=8095 eureka.instance.hostname=127.0.0.1:8095 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8096/eureka/,http://127.0.0.1:8097/eureka/ #server2 spring.application.name=eureka-server server.port=8096 eureka.instance.hostname=127.0.0.1:8096 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8095/eureka/,http://127.0.0.1:8097/eureka/ #server3 spring.application.name=eureka-server server.port=8097 eureka.instance.hostname=127.0.0.1:8097 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8095/eureka/,http://127.0.0.1:8096/eureka/
二. 创建服务端
###服务端
- pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
- yml
server: port: 8082 spring: application: name: producer-server eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/
- 启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class ProducerApp { public static void main(String[] args) { SpringApplication.run(ProducerApp.class, args); } }
- 创建UserController
package com.wxd.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Value("${server.port}") private String port; @GetMapping("/get") public String getPort() { return "Producer Server port: " + port; } }
这里只是简单的写一个服务。集成数据库等自己完成。
访问接口如下图
三. 创建客户端
###消费端
-
pom
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.4.6.RELEASE</version> </dependency>
-
yml
server: port: 8083 spring: application: name: consumer-server eureka: client: serviceUrl: #注册中心地址 多个用逗号隔开 defaultZone: http://localhost:8081/eureka/ #开启断路器 feign: hystrix: enabled: true
-
启动类
package com.wxd; 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.openfeign.EnableFeignClients; @EnableDiscoveryClient//注册中心 @EnableFeignClients//开启feign 声明式REST, 里面包括Hystrix 断路器 @SpringBootApplication @EnableCircuitBreaker//开启Hystrix 断路器 public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class, args); } }
-
创建RestTemplate
package com.wxd.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class MyConfiguration { @LoadBalanced//使用负载 @Bean RestTemplate restTemplate() { return new RestTemplate(); } }
-
创建UserHystrix
测试Hystrixpackage com.wxd.service; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.stereotype.Component; /** * 测试Hystrix */ @Component public class UserHystrix { @HystrixCommand(fallbackMethod = "defaultGetPort2") public String getPort2(){ throw new RuntimeException(""); } public String defaultGetPort2(){ return "服务错误"; } }
-
创建 UserService
测试调用服务 及 Hystrix回退package com.wxd.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; @Component @FeignClient(value = "producer-server", fallback = UserServiceHystrix.class) public interface UserService { @GetMapping("/get") String getPort(); @GetMapping("/get1") // @HystrixCommand(fallbackMethod = "defaultGetPort2") 和 @FeignClient不能一起使用 String getPort2(); default String defaultGetPort2(){ return "服务错误"; } }
-
创建 UserServiceHystrix
package com.wxd.service; import org.springframework.stereotype.Component; @Component public class UserServiceHystrix implements UserService { @Override public String getPort() { return "Producer Server 的服务调用失败"; } @Override public String getPort2() { return "服务错误2"; } }
-
创建UserController
package com.wxd.controller; import com.wxd.service.UserHystrix; import com.wxd.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class UserController { @Autowired private UserService userService; @Autowired private RestTemplate restTemplate; @Autowired private UserHystrix userHystrix; @GetMapping("/get") public String getPort() { return "consumer get Producer Server port: " + userService.getPort(); } @GetMapping("/get3") public String getPort3() { return "consumer get Producer Server port: " + userService.getPort2(); } @GetMapping("/get2") public String getPort2() { return "consumer get2 Producer Server port: " + restTemplate.getForObject("http://producer-server/get",String.class); } }
结果如下:
四. 创建 zuul
###网关zuul -
pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> <version>1.4.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
-
启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy //启动网关路由 public class ZuulApp { public static void main(String[] args) { SpringApplication.run(ZuulApp.class,args); } }
-
yml
简单实现
注意:首先要有注册中心eureka-server和cloud-producer模块
spring: application: name: cloud-gateway-zuul server: port: 8808 eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/
直接访问
http://localhost:8084/producer-server/get 或者
http://localhost:8084/zuul/producer-server/get
就可以直接路由到producer-server/get配置映射 Zuul指定path和serviceId
zuul: ignoredServices: '*'#忽略所有的服务 routes: producer-server: # producer-server只是一个标识,保证唯一即可 path: /pro/** # 映射的路径 serviceId: producer-server # 服务id 必须注册服务 url: http://localhost:8082/ #可以是url 和 serviceId 二选一
访问路径
http://localhost:8084/pro/get
五. 创建config-server
###config-server -
pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--表示为web工程--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--暴露各种指标 貌似是必须的 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
yml
server: port: 8085 spring: application: name: config-server cloud: config: server: git: uri: http://192.168.10.206/wxd/config.git#githttp地址 search-paths: prducer/*#git下的文件夹,可以写多个和使用* username: wxd password: 12345678 eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/#注册中心实现高可用
-
启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @SpringBootApplication @EnableConfigServer//开启config服务 public class ConfigServerApp { public static void main(String[] args) { SpringApplication.run(ConfigServerApp.class, args); } }
-
准备工作在自己的github创建一个项目
我这里在项目中新建一个prducer文件夹,在这个文件夹下新建文件config-client-dev.properties内容:dburl=http://loachost/1111111111111111
-
访问路径
http://localhost:8085/config-client/dev
http://localhost:8085/config-client-dev.properties
实现高可用需要部署多台服务器
六. 创建config-client
###config-client
- pom
<!--Spring Cloud Config 客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--Spring Boot Actuator,感应服务端变化--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
- yml
server: port: 8086 spring: application: name: config-client#名字必须和配置文件名字相同config-client-dev.properties cloud: config: profile: dev label: master # uri: http://localhost:8085/ #单节点模式 discovery:#负载模式 如果是负载模式,必须注册到注册中心 enabled: true service-id: config-server eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/ management: security: #SpringBoot 1.5.X 以上默认开通了安全认证,如果不关闭会要求权限 enabled: false endpoints: web: exposure: include: health, info, refresh #暴露接口,实现半自动化刷新
关键:这里是bootstrap.yml不是application.yml 因为bootstrap.yml优先级高
- 启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class ConfigClientApp { public static void main(String[] args) { SpringApplication.run(ConfigClientApp.class, args); } }
- Controller
package com.wxd.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope //开启更新功能 @RequestMapping("api") public class ConfigController { @Value("${dburl:asd}") private String fromValue; /** * 返回配置文件中的值 */ @GetMapping("/from") @ResponseBody public String returnFormValue(){ return fromValue; } }
- 测试
- 访问路径 http://localhost:8086/api/from 返回 http://loachost/1111111111111111
- 在git上修改文件,访问http://localhost:8086/actuator/refresh [post请求] 实现刷新配置
- 再次访问 http://localhost:8086/api/from 配置已经修改
不能实现动态刷新,需要手动刷新。需要优化
七. 创建OAth2-server
OAth2-server 认证与授权服务
- pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 开启负载使用时,需要注册到服务中心 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
- yml
server: port: 8087 spring: application: name: cloud-OAuth2-server eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/
- 启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; @SpringBootApplication @EnableResourceServer//开启资源服务,因为程序需要对外暴露获取token的API接口 public class OAuth2ServerApp { public static void main(String[] args) { SpringApplication.run(OAuth2ServerApp.class, args); } }
- 创建AuthorizationServerConfig
开启授权服务的功能
package com.wxd.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @Configuration @EnableAuthorizationServer //开启授权服务的功能 public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { String finalSecret = new BCryptPasswordEncoder().encode("123456"); //ClientDetailsServiceConfigurer配置了客户端的一些基本信息 clients.inMemory() // //将客户端的信息存储在内存中 .withClient("client") // client_id /创建了一个client名为browser的客户端 .secret(finalSecret) // client_secret .authorizedGrantTypes(/*"implicit",*/"password", "refresh_token") // 该client允许的授权类型 .scopes("app"); // 允许的授权范围 } /** * 设置管理器 * @param endpoints * @throws Exception */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints//.tokenStore(new MyRedisTokenStore(redisConnectionFactory))//Token的存储方式为内存 .authenticationManager(authenticationManager)//WebSecurity配置好的 // .userDetailsService(userServiceDetail);//读取用户的验证信息 .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // 允许表单认证 security.allowFormAuthenticationForClients(); } // @Override // public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { // //配置获取Token的策略 // oauthServer // .tokenKeyAccess("permitAll()") //对获取Token的请求不再拦截 // .checkTokenAccess("isAuthenticated()"); //验证获取Token的验证信息 // // } }
- 创建ResourceServerConfig
由于 auth-service 需要对外暴露检查 Token 的API接口,所以 auth-service 也是一个资源服务,需要在工程中引入 Spring Security,并做相关配置,对 auth-service 资源进行保护。
package com.wxd.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http. csrf().disable() .authorizeRequests().anyRequest().authenticated() .and() .httpBasic(); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { super.configure(resources); } }
- 创建WebSecurityConfig
获取token如图:package com.wxd.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // @Autowired // private UserDetailsServiceImpl userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } /** * 创建两个简单的用户用户测试 * * 也可以自己实现 * @return */ @Bean @Override protected UserDetailsService userDetailsService() { BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); String finalPassword = bCryptPasswordEncoder.encode("123456"); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("user_1").password(finalPassword).authorities("USER").build()); manager.createUser(User.withUsername("user_2").password(finalPassword).authorities("USER").build()); return manager; } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()) .passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatchers().anyRequest() .and() .authorizeRequests() .antMatchers("/oauth/**").permitAll(); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/favor.ioc"); } }
- 创建UserController
本例采用 RemoteTokenService 这种方式对 Token 进行验证。如果其他资源服务需要验证 Token,则需要远程调用授权服务暴露的验证 Token 的API接口。
package com.wxd.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.security.Principal; /** * <p>必须要有,做验证</p> * Created by Mr.Yangxiufeng on 2017/12/29. * Time:10:43 * ProjectName:Mirco-Service-Skeleton */ @RestController public class UserController { //暴露Remote Token Services接口 //如果其它服务需要验证Token,则需要远程调用授权服务暴露的验证Token的API接口 @RequestMapping("/user") public Principal user(Principal user) { return user; } }
这里只是简单的写一个服务。用户权限等需要自己实现。
八.创建需要鉴权的服务
###鉴权服务
- pom
<!-- 开启负载--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- yml
server: port: 8088 spring: application: name: cloud-OAuth2-client #单点测试 #security: # oauth2: # client: # accessTokenUri: http://localhost:8087/oauth/token # userAuthorizationUri: http://localhost:8087/oauth/authorize # clientId: client # clientSecret: 123456 # grantType: client_credentials,password # scope: app # resource: # userInfoUri: http://localhost:8087/user #负载 使用服务调用的方式。 security: oauth2: client: accessTokenUri: http://cloud-OAuth2-server/oauth/token userAuthorizationUri: http://cloud-OAuth2-server/oauth/authorize clientId: client clientSecret: 123456 grantType: client_credentials,password scope: app resource: userInfoUri: http://cloud-OAuth2-server/user loadBalanced: true eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/
- 启动类
package com.wxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class OAuth2ClientApp { public static void main(String[] args) { SpringApplication.run(OAuth2ClientApp.class, args); } }
- 创建OAuth2ClientConfig
package com.wxd.config; import feign.RequestInterceptor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; import org.springframework.web.client.RestTemplate; @EnableOAuth2Client @EnableConfigurationProperties @Configuration public class OAuth2ClientConfig { @Bean @ConfigurationProperties(prefix = "security.oauth2.client")//获取Bean的配置属性 public ClientCredentialsResourceDetails clientCredentialsResourceDetails() { //配置受保护资源的信息 return new ClientCredentialsResourceDetails(); } @Bean public RequestInterceptor oauth2FeignRequestInterceptor() { //配置一个过滤器,存储当前请求和上下文 //在request域内创建 AccessTokenRequest 类型的Bean。 return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), clientCredentialsResourceDetails()); } @Bean public OAuth2RestTemplate clientCredentialsRestTemplate() { //向认证中心服务请求的 return new OAuth2RestTemplate(clientCredentialsResourceDetails()); } }
- 创建ResourceServerConfiguration
package com.wxd.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true)//注解开启在方法上的保护功能 public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/order/**").authenticated(); // 配置order访问控制,必须认证后才可以访问 } }
- 创建OAuth2Controller
package com.wxd.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.security.Principal; @RestController public class OAuth2Controller { Logger logger = LoggerFactory.getLogger(OAuth2Controller.class); @GetMapping("/person") @PreAuthorize("hasAuthority('USER1')")//需要ROLE_ADMIN权限 public @ResponseBody Object personInfo() { return "{ad:asd}"; } @GetMapping("/product/{id}") public String getProduct(@PathVariable String id) { return "product id : " + id; } @GetMapping("/order/{id}")//不需要任何权限,只要Header中的Token正确即可 public String getOrder(@PathVariable String id) { return "order id : " + id; } //获取当前“Token”用户信息 token是入参 @GetMapping("/getPrinciple") public OAuth2Authentication getPrinciple(OAuth2Authentication oAuth2Authentication, Principal principal, Authentication authentication) { logger.info(oAuth2Authentication.getUserAuthentication().getAuthorities().toString()); logger.info(oAuth2Authentication.toString()); logger.info("principal.toString() " + principal.toString()); logger.info("principal.getName() " + principal.getName()); logger.info("authentication: " + authentication.getAuthorities().toString()); return oAuth2Authentication; } }
http://localhost:8088/getPrinciple?access_token=ff71fcb6-5963-4c2e-9438-8704ce93824c
http://localhost:8088/order/1?access_token=1cab1803-8b0d-4a3e-818a-52434d18a23e
这里只是简单的写一个服务。集成数据库等自己完成。
总的项目结构如图: