1、jdk:1.8
2、springboot 2.1.6.RELEASE ,springcloud Greenwich.SR6
应用权限概述权限,是整个微服务体系乃至软件业永恒的话题,有资源的地方,就有权限约束。
Spring Security 是 Spring Resource 社区的一个安全组件, Spring Security 为 JavaEE 企业红开发提供了全面的安全防护。安全防护是一个不断变化的目标, Spring Security 通过版本不断迭代来实现这一目标。 Spring Security 采用“安全层”的概念,使每一层都尽可能安全,连续的安全层可以达到全面的防护。 Spring Seeurity 可以在 Controller 层、 Service 层、 DAO 层等以加注解的方式来保护应用程序的安全。 Spring Security 提供了细粒度的权限控制,可以精细到每一个 API 接口、每一个业务的方法,或者每一个操作数据库的 DAO 层的方法。 Spring Security 提供的是应用程序层的安全解决方案,一个系统的安全还需要考虑传输层和系统层的安全,例如采用 Htpps 协议、服务器部署防火墙等。
Spring Security 是一个提供身份验证、授权和针对常见攻击的保护的框架。凭借对保护命令式和反应式应用程序的一流支持,它是保护基于 Spring 的应用程序的事实上的标准。
1、创建cloud-security项目,引入依赖
<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>
2、创建Spring Security配置
代码如下:
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication().passwordEncoder(passwordEncoder)
.withUser("root").password(passwordEncoder.encode("1234")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder.encode("admin")).roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().anyRequest().fullyAuthenticated();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 禁用csrf,关闭劫持
http.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/actuator/hystrix.stream","/turbine.stream");
}
}
3、eureka-consumer消费端引入cloud-security模块
<dependency>
<groupId>site.sunlong</groupId>
<artifactId>cloud-security</artifactId>
<version>${project.version}</version>
</dependency>
4、测试
浏览器输入消费端,http://localhost:7001/consumer/feign/hello,会出现Spring Security登录页面,输入用户名root,密码1234
出现如下页面,则表示成功
实际项目中,对于服务接口的访问基本都是通过网关进行访问的,所以网关安全也很重要。
1、在之前的项目springcloud 项目搭建(6) 网关 zuul中添加Spring Security依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、修改配置文件
#spring security 配置
spring.security.user.name=zuul-user
spring.security.user.password=zuul-password
3、测试
分别启动eureka-server、zuul-gateway、user-provider,其中user-provider被zuul-gateway代理,
访问zuul-gateway的http://localhost:8501/zuul-proxy/user-providers-proxy/user/getUserName/55,弹出登录页面
输入在zuul-gateway中配置的用户名密码,接口访问成功
如果要通过Feign 访问接口的话也需要被调用方接口安全认证。
启动eureka-server、zuul-gateway、user-provider、eureka-consumer,其中user-provider被zuul-gateway代理,eureka-consumer通过zuul-gateway去调用user-provider的接口。
浏览器输入http://localhost:7001/consumer/feign/getUserName/hhh,如果未登录会出现上述消费者安全访问中的情况,登录过后会发现控制台出现以下报错信息
feign.FeignException$Unauthorized: status 401 reading UserProviderClientService#getUserName(String)
at feign.FeignException.clientErrorStatus(FeignException.java:161)
at feign.FeignException.errorStatus(FeignException.java:141)
at feign.FeignException.errorStatus(FeignException.java:133)
报错原因是zuul-gateway的访问是需要用户名密码的,通过Feign 访问的时候没有认证授权,所以要添加认证授权的信息。
在eureka-consumer端修改FeignClientConfig配置文件,添加认证授权信息
代码如下:
@Configuration
public class FeignClientConfig {
/**
* feign 日志打印
* @return
*/
@Bean
public Logger.Level getFeignLoggerLevel() {
return feign.Logger.Level.FULL;
}
/**
* Feign访问zuul 认证授权
* @return
*/
@Bean
public BasicAuthRequestInterceptor getBasicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("zuul-user", "zuul-password");
}
}
重启eureka-consumer再次访问http://localhost:7001/consumer/feign/getUserName/hhh,访问成功
如果配置BasicAuthRequestInterceptor不起作用的话,可以在FeignClient注解的configuration属性添加FeignClientConfig
示例如下:
@FeignClient(name = "ZUUL-GATEWAY" , path = "zuul-proxy/user-providers-proxy/user" ,fallbackFactory = UserProviderServiceFallbackFactory.class,configuration = FeignClientConfig.class)
public interface UserProviderClientService {
@GetMapping("/getUserName/{username}")
String getUserName(@PathVariable("username") String username);
}
一般情况下 Eureka 和服务的提供注册者都会在一个内网环境中,但免不了在某些项目中需 要让其他外网的服务注册到 Eureka,这个时候就有必要让 Eureka 增加一套安全认证机制了, 让所有服务提供者通过安全认证后才能注册进来。
1、eureka-server端引入Spring Security依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、修改eureka-server 配置文件,添加spring.security 配置
#spring.security 配置
spring.security.user.name=eurekaUser
spring.security.user.password=eurekaUserPassword
3、修改所有eureka客户端
把之前的
eureka.client.service-url.defaultZone=http://localhost:8001/eureka
修改为
eureka.client.service-url.defaultZone=http://eurekaUser:eurekaUserPassword@localhost:8001/eureka
重启eureka-server和eureka客户端,访问http://localhost:8001/,跳到登录页,登录了才能访问
登录之后看到了eureka客户端也注册进来了。
至此,springcloud Spring Security 安全与权限简单入门就完成了。
感兴趣的可以关注一下我的springcloud专栏
GitHub地址:
https://github.com/ArronSun/micro-services-practice.git
参考书籍:
《深入理解springcloud与微服务构建》
《重新定义springcloud 实战》
能力一般,水平有限,如有错误,请多指出。