SpringCloud - Spring Cloud 之 Security服务安全机制(二十)

阅读本文前可先参考

​​​​​​SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客

Spring Security

微服务的Rest服务都是基于http请求的,因此很有可能暴露在公网上,任何人都可能调用访问,如果Rest服务有一些私密信息,就会导致信息的泄露,因此我们需要给微服务增加安全机制。如:Spring Security

Spring Security 是 Spring Resource 社区的一个安全组件, Spring Security 为 JavaEE 企业开发提供了全面的安全防护。

Spring Security 采用“安全层”的概念,使每一层都尽可能安全,连续的安全层可以达到全面的防护

Spring Seeurity 可以在 Controller 层、 Service 层、 DAO 层等以加注解的方式来保护应用程序的安全。

Spring Security 提供了细粒度的权限控制,可以精细到每一个 API 接口、每一个业务的方法,或者每一个操作数据库的 DAO 层的方法。

Spring Security 提供的是应用程序层的安全解决方案,一个系统的安全还需要考虑传输层和系统层的安全,例如采用 Htpps 协议、服务器部署防火墙等。

Spring Security 是一个提供身份验证、授权和针对常见攻击的保护的框架。凭借对保护命令式和反应式应用程序的一流支持,它是保护基于 Spring 的应用程序的事实上的标准

一、服务提供者集成 Security 安全认证

1、创建一个 springboot Module 服务提供者 springcloud-11-service-security-provider

SpringCloud - Spring Cloud 之 Security服务安全机制(二十)_第1张图片  

2、添加 spring-boot-starter-security等 依赖



    org.springframework.boot
    spring-boot-starter-security

    
        com.company
        springcloud-demo
        1.0.0
    

    com.company
    springcloud-11-service-security-provider
    1.0.0

    springcloud-11-service-security-provider
    Demo project for Spring Boot

    
        1.8
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            mysql
            mysql-connector-java
        

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.2.2
        

        
        
            com.company
            springcloud-2-service-common
            1.0.0
        

        
        
            org.springframework.boot
            spring-boot-devtools
            true
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

        
        
            org.springframework.boot
            spring-boot-starter-security
        

    

    

        
        
            
                src/main/java
                
                    **/*.xml
                
            

            
                src/main/resources
                
                    **/*.*
                
            
        

        

            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

3、application.properties配置文件中添加安全认证账号密码

#安全认证;配置访问账号和密码
spring.security.user.name=admin
spring.security.user.password=123456
server.port=9001

#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-11-service-security-provider

#设置mysql数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin123456

#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
eureka.instance.lease-renewal-interval-in-seconds=5
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=10
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false

#注册服务实例名称
eureka.instance.instance-id=springcloud-11-service-security-provider
#注册中心的链接地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka


#安全认证;配置访问账号和密码
spring.security.user.name=admin
spring.security.user.password=123456

4、创建 controller,mapper,model等文件基于RESTFUL风格访问

@RestController
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @GetMapping(value = "/eureka/security/goodList")
    public List goodList(){
        List goodsList = goodsService.getAllGoods();

        System.out.println("查询商品列表成功:");
        for (Goods good:goodsList) {
            System.out.println("查询商品:"+ good);
        }
        return goodsList;
    }
}

5、启动springboot 启动类,输入 http://localhost:9001/eureka/security/goodList

访问,首先会进入安全登录页,输入账号密码即可访问

SpringCloud - Spring Cloud 之 Security服务安全机制(二十)_第2张图片

注:

在这里,遇到一个坑,因为刚开始复制的 Sleuth + Zipkin 模块的项目,因此运行 导致只能访问一次,应该是 Spring CLoud内部版本之间有点冲突,去掉 Sleuth + Zipkin 依赖即可

二、服务消费者集成 Security 安全认证

当远程的服务提供者使用了 密码安全验证,此时服务的消费方如果想直接访问服务提供者就不能访问,需要对服务消费者 进行配置处理

1、RestTemplate 调用

1、创建一个 springboot Module 服务消费者 springcloud-11-service-security-consumer

SpringCloud - Spring Cloud 之 Security服务安全机制(二十)_第3张图片

2、pom.xml文件如下:


    
        com.company
        springcloud-demo
        1.0.0

    

    com.company
    springcloud-11-service-security-consumer
    1.0.0

    springcloud-11-service-security-consumer
    Demo project for Spring Boot

    
        1.8
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            com.company
            springcloud-2-service-common
            1.0.0
        

        
        
            org.springframework.boot
            spring-boot-devtools
            true
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

3、application.properties配置文件

server.port=8081

#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-11-service-security-consumer

#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
eureka.instance.lease-renewal-interval-in-seconds=30
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=60
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false

#注册服务实例名称
eureka.instance.instance-id=springcloud-11-service-security-consumer
#注册中心的链接地址
#eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka

4、 在RestConfig配置类中添加 HttpHeaders(org.springframework.http.HttpHeaders)

@Configuration
public class RestConfig {

    //使用Ribbon实现负载均衡的调用
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate () {
        return new RestTemplate();
    }

    /**
     * 进行 Http头信息配置实现安全认证
     */
    @Bean
    public HttpHeaders getHeaders(){
        //定义 HTTP 头部信息
        HttpHeaders headers = new HttpHeaders();
        /*
        认证的账户密码
        服务提供者 application.properties 配置文件中 安全认证配置的访问账号和密码
        spring.security.user.name=admin
        spring.security.user.password=123456
        * */
        String auth = "admin:123456";

        //加密处理
        byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));
        String authHeader = "Basic " + new String(encodedAuth);
        headers.set("Authorization", authHeader);
        return headers;
    }
}

5、在controller中调用的地方注入该HttpHeaders,且传入这个http头信息

@RestController
public class GoodsController {
    private final String GOODS_SERVICE_URL = "http://localhost:9001/service/goodList";

    private final String GOODS_SERVICE_EUREKA_URL = "http://springcloud-11-service-security-provider/eureka/security/goodList";

    @Autowired
    private RestTemplate restTemplate;

    //HttpHeaders这个bean注入到controller中
    @Autowired
    private HttpHeaders httpHeaders;

    @GetMapping(value = "/springcloud/security/goodList")
    public @ResponseBody Object getGoodList(){
        //调用远程的一个controller(Restful风格调用)
        ResponseEntity responseEntity = restTemplate.exchange(GOODS_SERVICE_EUREKA_URL, HttpMethod.GET, new HttpEntity(httpHeaders),Object.class);

        return responseEntity.getBody();
    }
} 
  

6、依次启动Eureka,服务提供者,服务消费者 访问

http://localhost:8081/springcloud/security/goodList

注:

eureka中也配置了安全认证 

eureka中application.properties


#指定服务注册中心的位置  eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka


#安全认证;配置访问config配置中心的访问账号和密码
spring.security.user.name=admin
spring.security.user.password=123456

提供者中

eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka


#安全认证;配置访问账号和密码
spring.security.user.name=admin
spring.security.user.password=123456

消费者中

#注册服务实例名称
eureka.instance.instance-id=springcloud-11-service-security-consumer
#注册中心的链接地址
#eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka

2、OpenFeign 调用

1、 在 springcloud-2-service-common 公共模块新增一个 FeignConfiguration 配置类

SpringCloud - Spring Cloud 之 Security服务安全机制(二十)_第4张图片

@Configuration
public class FeignConfiguration {

    //@RequestLine("GET /eureka/security/goodList")

    /**
     * 一种契约,采用feign的契约方式,如果不配置该bean,会转成SpringMVC的方式
     */
    /*@Bean
    public Contract feignContract(){
        return new Contract.Default();
    }*/

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
        //传用户名和密码
        return new BasicAuthRequestInterceptor("admin","123456");
    }
}

2、 新增一个 服务声明接口 ProviderSecurityGoodsRemoteClient 

@Component
@FeignClient(value = "springcloud-11-service-security-provider",
        /*fallback = HystrixProviderGoodsRemoteClientFallBack.class,*/
        fallbackFactory = HystrixProviderGoodsRemoteClientFallBackFactory.class,
        configuration = FeignConfiguration.class)
public interface ProviderSecurityGoodsRemoteClient {

    /**
     * 声明一个feign的接口,它的实现是服务提供者的controller实现
     */
    @GetMapping(value = "/eureka/security/goodList")
    public List goods();
}

3、服务消费者引入依赖


        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            com.company
            springcloud-2-service-common
            1.0.0
        

        
        
            org.springframework.boot
            spring-boot-devtools
            true
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

    

4、消费者启动类添加注解

@EnableFeignClients  //表示开启 Spring Cloud OpenFeign的支持功能
@EnableEurekaClient  //开启 Eureka client服务
@SpringBootApplication
public class Security11ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Security11ConsumerApplication.class, args);
    }
}

5、消费者controller调用

@RestController
public class GoodsController {

    @Autowired
    private ProviderSecurityGoodsRemoteClient providerSecurityGoodsRemoteClient;


    @GetMapping(value = "/springcloud/security/openfeign/goodList")
    public @ResponseBody Object getGoodListOpenFeign(){

        // 调用远程的一个controller, restful的调用,通过openfeign这种声明式的远程调用,providerGoodsRemoteClient就像dubbo里面的接口层一样
        return  providerSecurityGoodsRemoteClient.goods();
    }
}

浏览器输入http://localhost:8081/springcloud/security/openfeign/goodList

注:

在这里,遇到一个坑,因为刚开始复制的 Sleuth + Zipkin 模块的项目,因此运行 导致只能访问一次,应该是 Spring CLoud内部版本之间有点冲突,去掉 Sleuth + Zipkin 依赖即可

三、安全服务模块/项目

在实际项目开发中,服务一般会非常多,绝大多数服务都需要用到安全验证,账户密码基本一样,如果每个服务都单独配置安全认证,繁琐重复劳动不是我们提倡的,因此单独建立一个安全服务验证的项目,其他微服务如果需要安全认证就引入该项目的依赖即可

1、新建一个模块 springcloud-11-service-security-auth

2、添加 spring-boot-starter-security 依赖


    
        com.company
        springcloud-demo
        1.0.0
    

    com.company
    springcloud-11-service-security-auth
    1.0.0

    springcloud-11-service-security-auth
    Demo project for Spring Boot

    
        1.8
    

    

        
        
            org.springframework.boot
            spring-boot-starter-security
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

3、新增配置类 WebSecurityConfiguration

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("admin")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("USER","ADMIN")
                .and()
                .withUser("root")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("USER","ROOT");
    }

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.httpBasic().and().authorizeRequests().anyRequest().fullyAuthenticated();
        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //把csrf拦截置为不可用,401问题
        httpSecurity.csrf().disable();
    }
}

4、在服务提供者模块中引入本模块依赖,启动运行测试即可


        
            com.company
            springcloud-11-service-security-auth
        

SpringCloud - Spring Cloud 之 Security服务安全机制(二十)_第5张图片

 这里的UI界面会和之前有些区别

1、之前界面是spring封装的security

2、当前是使用的security自己的jar包

你可能感兴趣的:(SpringCloud,spring,cloud,Security)