摘要:隨着雲計算的發展,微服務、先後端分離、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"); }