摘要:随着云计算的发展,微服务、先后端分离、DevOps逐渐成为架构主流。而不一样于以往的单体应用,微服务大多仅以api形式专递信息,而且无状态(不记录用户登陆状态及会话内容),这就为整个系统带来权限认证的问题。因而Token(令牌)成为解决权限认证的手段,目前主要方法有OAuth、JWT以及OpenID。本文主要带来是基于OAuth2标准的实践分享。java
OAuth是一个关于受权(authorization)的开放网络标准,在全世界获得普遍应用,目前的版本是2.0版。OAuth主要用户第三方受权,例如在一些网站,咱们能够直接用微信、微博帐号直接登陆,其网站使用的就是OAuth标准。spring
固然,咱们也可使用OAuth做为微服务的认证,原理很简单,把各个微服务当作各个网站,而登陆受权中心则是由“微信”、“微博”换成了OAuth,因而咱们拿着“微信”、“微博”的帐号便可使用各个微服务。后端
对于OAuth的理解,能够参考一下两篇文章。api
OAuth2.0标准-标准文档安全
理解OAuth 2.0-阮一峰服务器
在此为了简要说明OAuth认证过程,附上OAuth认证的基本流程:微信
+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
受权服务配置 因为OAuth在Spring Security中有完整实现,咱们直接添加spring cloud starter oauth2的这个依赖集合便可知足咱们的要求。网络
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>
接下来进行受权服务端的配置。该配置须要实现AuthorizationServerConfigurerAdapter
这个类,并加上注解@EnableAuthorizationServer
便可。架构
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { }
接下来咱们要实现父类中的三个配置方法前后端分离
服务端端点配置 在服务器端点配置主要配置三点:1.认证管理器 2.用户信息 3.token的存储管理
@Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @Bean public RedisTokenStore tokenStore() { return new RedisTokenStore(connectionFactory); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .authenticationManager(authenticationManager) .userDetailsService(userDetailsService) .tokenStore(tokenStore()); }
服务端安全配置
@Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security .tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); }
客户端配置
@Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("my-client") .scopes("xx") .secret("123456") .authorizedGrantTypes("password"); }