安全认证《十三》

在项目中各个服务模块产生的接口并不希望被第三方滥用,所以在向外暴露接口的网关服务中增加了拦截器,并对其进行了简单的安全限制。

但在实际需求中,微服务所产生的接口可能会服务于本系统的多个客户端:iOS,Android,web,pc 等,或者将这些接口开放给第三方系统使用。在提供服务的同时需要一套授权机制来保护安全,在网关服务中增加拦截器的做法略简单,为此spring 提供了spring security 框架来解决这一问题,并且实现了oAuth2.0协议对各类客户端进行授权管理。

OAuth2.0 协议介绍:

OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。

OAuth2.0 是OAuth协议的下一版本,但不向后兼容OAuth1.0 。OAuth2.0关注客户端开发者的简易性,同时为web应用,桌面应用,手机提供专门的认证流程,目前主要使用的版本是OAuth2.0 。

  

协议参与者

Resource owner

资源所有者,对资源具有授权能力的人

Resource server

资源服务器,它存储资源,并处理对资源的访问请求

扫描二维码关注公众号,回复: 2652090 查看本文章

Client

第三方应用,它获得RO的授权后便可去访问RO的资源

Authorization Server

授权服务器

  1. 客户端向资源所有者(用户)请求授权
  2. 客户端收到授权许可
  3. 客户端于授权服务器进行身份认证并出示授权许可请求访问令牌
  4. 授权服务器验证客户端身份并验证授权许可,若有效则办法访问令牌
  5. 客户端从资源服务器请求受保护资源并出示访问令牌进行身份验证
  6. 资源服务器验证访问令牌,若有效则满足该请求

授权模式:

OAuth2.0定义了四种授权模式。

1.授权码模式:是功能最完整,流程最严密的授权模式。它的特点就是通过客户端的后台服务器,于服务提供商的认证服务器进行互动。

2.简化模式:不通过第三方应用程序的服务器,而是直接在浏览器中向认证服务器申请令牌,跳过了“授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

3.密码模式:用户向客户端提供自己的用户名和密码。客户端使用这些信息,向服务商提供商索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得存储密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

4.客户端模式:指客户端以自己的名义,而不是以用户的名义,向服务提供商进行认证。严格地说,客户端模式并不属于oauth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求服务提供商提供服务,其实不存在授权问题。

在Dubbo 中使用OAuth2.0

dubbo 框架中的网关模块代理了dubbo服务的web调用,并将这些服务转化为HTTP协议的API接口。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.security.oauth</groupId>
   <artifactId>spring-security-oauth2</artifactId>
   <version>2.0.9.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

spring-boot-starter-security

 

Spring安全框架

spring-security-oauth2

Spring 安全框架的oauth2.0协议扩展

spring-boot-starter-data-redis

引入redis缓存高频调用的access token信息以提高性能

application.properties:

spring.redis.host=localhost
spring.redis.database=0
spring.redis.port=6379
spring.security.oauth2.resource.filter-order=6

security.oauth2.resource.filter-order :设置OAuth 框架过滤器的级别。

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    public void configure(HttpSecurity http) throws Exception{
       http.authorizeRequests()
               .antMatchers(HttpMethod.OPTIONS).permitAll().antMatchers("/public/{id}").permitAll()
               .and()
               .authorizeRequests()
               .anyRequest()
               .authenticated()
               .and()
               .httpBasic();
    }
}

每个服务提供的URL接口便是资源,通过继承ResourceServerConfigurerAdapter类并重写configure 方法完成对资源的配置,有点类似于过滤器限制所要连接的URL。并通过@EnableResourceServer注解表示该应用为资源服务。

HttpSecurity 是 securityBuilder 接口的实现类,用于构建HTTP安全相关的配置,并且可以通过链式编程的方式完成自定义的配置。

authorizeRequests

注册url 规则权限匹配

antMatchers

匹配请求

permitAll

不进行权限拦截

anyRequest

任何请求

authenticated

进行认证

httpBasic

开启HTTP基础认证

and

连接符

通过继承AuthorizationServerConfigurerAdapter配置授权服务策略,并使用@EnableAuthorizationServer注解表示该应用是授权服务应用。

ClientDetailsServiceConfigurer配置客户端授权管理信息,如果拥有多个客户端(开放平台系统),可以根据提供的clientId从数据库中查询,并将各相关配置提交给BaseClientDetails。

setClientId

客户端ID ,必要

SetClientSecret

客户端密码

SetScope

权限范围

setAccessTokenValiditySeconds

 

Token创建时的超时时间

SetRefershTokenValiditySeconds

Token刷新时间

SetAuthorities

客户端拥有的身份

SetAuthorizedGrantTypes

客户端拥有的授权方式

Password

密码模式

Client_credentials

客户端模式

Refresh_token

刷新token

Implicit

简化模式

AuthorizationServerEndpointsConfigurer

 

用于配置授权管理器策略于存储token的策略,通过注入token Store指定将token信息存储在redis中

EnableGlobalMethodSecurity

 

设置全局方法安全控制,通过prepostEnabled =true 设置在方法调用之前拦截,并进行权限验证

WebSecurityConfigurerAdapter

 

来自于spring web 安全管理框架,用于对访问web用户身份进行安全配置,需要配合@EnableWebSecurity注解开启安全验证

UserDetailsService

 

对应之前配置的app客户端所使用的password授权模式,在每次提交用户名于密码申请access_token时,spring security将与UserDetailsService所提供的用户信息做校验

User

接口实现类UserDetails()用于封装用户名,密码,角色等信息,并且需要按照格式ROLE_*指定用户角色

FilterRegistrationBean

 

spring security安全框架默认开启cors(跨域资源共享)机制进行跨域访问控制。配合之前在ResourceServerConfigurerAdapter中对OPTIONS类型请求不进行拦截,这里新建一个拦截器完成对cors的配置。[浏览器在发起跨域请求时,会首先向目标服务器发起一个options请求,用于询问当前请求的域是否允许,如果允许则返回数据,否则将提示跨域错误,并拦截返回信息]

PasswordEncoder

一般情况下数据库中存储的用户密码会经过加密处理,但是用户申请access_token提交的则是明文密码,如果不指定校验密码时的加密策略肯定无法通过验证。这里通过注入passwordEncoder来告知spring security 使用bcrypt 策略进行加密。 同样,对应创建用户存储密码时可以使用new BcryptPasswordEncoder().encode(password)对密码进行加密处理

 

preAuthorize

对应@EnableGlobalMethodSecurity注解,在该方法调用之前进行拦截,并通过指定的spring EL表达式验证权限。该注解可以应用在任意spring管理的方法之上。

hasRole('ROLE_USER')

 

限定用户角色为ROLE_USER访问

Or,and

连接符

#oauth2.clientHasRole('ROLE_CLIENT')

 

限定客户端角色为ROLE_CLIENT访问

hasIpAddress(192.168.0/24)

限定IP地址为192.168.0.24的IP访问

HasAuthority(‘user’)

限定名为user的用户访问

Principal

在访问受保护资源时,需要提交access_token完成身份验证,通过在形参中注入principal便可获得当前访问的access_token所对应的用户名称

TokenStore

当用户修改了用户名或密码后,会涉及到重新生成access_token的需求。之前在配置spring security 的权限管理策略时通过注入token store 指定使用redis存储token 信息,同样也可以使用tokenstore找到token并删除。

部署应用后访问http://localhost:8080//public/1 成功返回结果,但是当访问/private/1时拦截器生效,提示需要授权才可以访问呢。

之前设置过web和app两个客户端,可以通过post 方式获取,但oauth2 协议中客户端信息需要使用basic auth方式传递,为了方便测试,可以使用chrome 浏览器的postman插件。

 

 

猜你喜欢

转载自blog.csdn.net/qq_35781178/article/details/81271796