1.搭建权限认证模块
1.1 创建myspringcloud-security模块,用于为服务生产者接口加密
1.2 配置POM依赖
<?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">
<parent>
<artifactId>myspringcloud</artifactId>
<groupId>com.en</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0</version>
<artifactId>myspringcloud-security</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
1.3 父工程添加此依赖
1.4 创建com.en.config路径,创建WebSecurityConfiguration.java配置类,为所有生产者服务接口加密
package com.en.config;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("root").password(new BCryptPasswordEncoder().encode("root")).roles("USER").
and().withUser("admin").password(new BCryptPasswordEncoder().encode("root")).roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().anyRequest()
.fullyAuthenticated();
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
1.5 生产者服务导入加密依赖
1.6 服务消费方RestConfig类修改,在Http头信息中加入加密验证信息
package com.en.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.Base64;
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
String auth = "admin:root";
byte[] encodedAuth = Base64.getEncoder()
.encode(auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
headers.set("Authorization", authHeader);
return headers;
}
}
1.7 服务消费方controller请求修改,调用时在http头中加入验证信息
package com.en.controller;
import com.en.po.ProductPo;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.List;
/**
* @ClassName ConsumerProductController
* @Description 服务消费方控制器
* @Author liuxiaobai
* @Date 2020年6月26日09:18:41
* @Version 1.0
**/
@RestController
@RequestMapping("/consumer")
public class ConsumerProductController {
private static final String PRODUCT_GET_URL = "http://localhost:8081/prodcut/getInfoById/";
private static final String PRODUCT_LIST_URL="http://localhost:8081/prodcut/getAllInfo/";
private static final String PRODUCT_ADD_URL = "http://localhost:8081/prodcut/addInfo/";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders httpHeaders;
@RequestMapping("/product/getInfoById")
public Object getProduct(long id) {
return restTemplate.exchange(PRODUCT_GET_URL + id,HttpMethod.GET,new HttpEntity<>(httpHeaders), ProductPo.class).getBody();
}
@RequestMapping("/product/getAllInfo")
public Object listProduct() {
return restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity<>(httpHeaders), List.class).getBody();
}
@RequestMapping("/product/addInfo")
public Object addPorduct(ProductPo productPo) {
return restTemplate.exchange(PRODUCT_ADD_URL, HttpMethod.POST,new HttpEntity<>(productPo,httpHeaders), Boolean.class).getBody();
}
}
1.8 重启生产者、消费者服务,浏览器验证接口调用,用户名:admin/root 密码:root/root
调用时提示输入验证信息,输入后生产者服务接口访问正常
消费者服务接口访问正常
2.搭建Eureka注册中心
2.1 新建Eureka服务端
2.2 导入POM依赖
<?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">
<parent>
<artifactId>myspringcloud</artifactId>
<groupId>com.en</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>myspringcloud-eureka</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<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.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
2.3 修改application.yml,配置eureka相关信息
server:
port: 7001
eureka:
instance: # eureak实例定义
hostname: localhost # 定义 Eureka 实例所在的主机名称
2.4 创建Eureka启动类
package com.en.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
2.5 修改服务生产者配置文件,将服务注册到Eureka
server:
port: 8081
mybatis:
mapper-locations: # 所有的mapper映射文件
- classpath:mapping/*.xml
spring:
application:
name: myspringcloud-provider-product
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=GMT%2B8 # 数据库连接地址
username: root
password: root
logging:
level:
com.en.mapper: debug
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: microcloud-provider-product
prefer-ip-address: true
info:
app.name: myspringcloud-provider-product
company.name: en
build.artifactId: $project.artifactId$
build.modelVersion: $project.modelVersion$
2.6 服务生产者启动类加入Eureka客户端注解
2.7 加入Eureka详细信息查看功能,修改服务生产者POM引入actuator模块
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.8 父工程修改POM
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$</delimiter>
</delimiters>
</configuration>
</plugin>
2.9 启动Eureka服务器,生产者服务注册成功
点进去可以看到详细信息
2.10 现在Eureka已经可以使用了,但启动的时候抱一个连接的错误,修改一下Eureka服务端配置文件
server:
port: 7001
eureka:
server:
eviction-interval-timer-in-ms: 1000 #设置清理的间隔时间,而后这个时间使用的是毫秒单位(默认是60秒)
client:
fetch-registry: false
register-with-eureka: false
instance: # eureak实例定义
hostname: localhost # 定义 Eureka 实例所在的主机名称
2.11 还有一个问题就是生产者服务宕机后,Eureka服务端还保留着生产者服务的信息,不久后会触发Eureka安全机制,解决方案为给生产者服务提供一个心跳检测,修改生产者服务配置文件
server:
port: 8081
mybatis:
mapper-locations: # 所有的mapper映射文件
- classpath:mapping/*.xml
spring:
application:
name: myspringcloud-provider-product
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=GMT%2B8 # 数据库连接地址
username: root
password: root
logging:
level:
com.en.mapper: debug
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: microcloud-provider-product
prefer-ip-address: true
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
info:
app.name: myspringcloud-provider-product
company.name: en
build.artifactId: $project.artifactId$
build.modelVersion: $project.modelVersion$
2.12 现在用SpringSecurity给Eureka提供一个安全认证,POM文件引入SpringSecurity依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.13 修改Eureka服务端application.yml文件,增加用户、密码验证
server:
port: 7001
eureka:
server:
eviction-interval-timer-in-ms: 1000 #设置清理的间隔时间,而后这个时间使用的是毫秒单位(默认是60秒)
client:
fetch-registry: false
register-with-eureka: false
service-url:
defaultZone: http://admin:root@localhost:7001/eureka
instance: # eureak实例定义
hostname: localhost # 定义 Eureka 实例所在的主机名称
spring:
security:
user:
name: admin
password: root
2.14 修改服务生产者application.yml文件,增加验证信息
defaultZone: http://admin:root@localhost:7001/eureka
2.15 在Eureka服务端新增权限配置类,关闭csrf劫持
package com.en.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class EurekaSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
super.configure(http);
}
}
2.16 重启服务,登录Eureka前端页面,提示输入用户名信息,登入后一切正常
2.17 优化Eureka高可用,配置Eureka集群,拷贝两份Eureka服务端,分别改名为Eureka2和Eureka3
2.18 修改本地hosts文件,新增如下内容
127.0.0.1 eureka
127.0.0.1 eureka2
127.0.0.1 eureka3
2.19 修改Eureka服务端1application.yml配置文件,修改端口以及注册位置,Eureka2和Eureka3同理
server:
port: 7001
eureka:
server:
eviction-interval-timer-in-ms: 1000 #设置清理的间隔时间,而后这个时间使用的是毫秒单位(默认是60秒)
client:
fetch-registry: false
register-with-eureka: false
service-url:
defaultZone: http://admin:root@eureka:7001/eureka,http://admin:root@eureka2:7002/eureka,http://admin:root@eureka3:7003/eureka
instance: # eureak实例定义
hostname: eureka # 定义 Eureka 实例所在的主机名称
spring:
security:
user:
name: admin
password: root
2.20 修改服务生产者Eureka注册地址
server:
port: 8081
mybatis:
mapper-locations: # 所有的mapper映射文件
- classpath:mapping/*.xml
spring:
application:
name: myspringcloud-provider-product
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=GMT%2B8 # 数据库连接地址
username: root
password: root
logging:
level:
com.en.mapper: debug
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://admin:root@eureka:7001/eureka,http://admin:root@eureka2:7002/eureka,http://admin:root@eureka3:7003/eureka
instance:
instance-id: microcloud-provider-product
prefer-ip-address: true
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
info:
app.name: myspringcloud-provider-product
company.name: en
build.artifactId: $project.artifactId$
build.modelVersion: $project.modelVersion$
2.21 全部服务重启,Eureka集群已生效,消费方接口调用正常
源码自取: