在spring cloud
需要使用oauth2
來實現多個微服務的統一認證授權,通過向oauth服務
發送某個類型的grant type
進行集中認證和授權,從而獲得access_token
,而這個token是受其他微服務信任的,我們在后續的訪問可以通過access_token
來進行,從而實現了微服務的統一認證授權。
本示例提供了四大部分:
-
discovery-service
:服務注冊和發現的基本模塊 -
auth-server
:oauth2認證授權中心 -
order-service
:普通微服務,用來驗證認證和授權 -
api-gateway
:邊界網關(所有微服務都在它之后)
oauth2中的角色:
-
resource server
:被授權訪問的資源 -
authotization server
:oauth2認證授權中心 -
resource owner
: 用戶 -
client
:使用api的客戶端(如android 、ios、web app)
grant type:
-
authorization code
:用在服務端應用之間 -
implicit
:用在移動app或者web app(這些app是在用戶的設備上的,如在手機上調起微信來進行認證授權) -
resource owner password credentials(password)
:應用直接都是受信任的(都是由一家公司開發的,本例子使用 -
client credentials
:用在應用api訪問。
1.基礎環境
使用postgres
作為賬戶存儲,redis
作為token
存儲,使用docker-compose
在服務器上啟動postgres
和redis
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
redis: image: sameersbn/redis:latest ports: - "6379:6379" volumes: - /srv/docker/redis:/var/lib/redis:z restart: always postgresql: restart: always image: sameersbn/postgresql: 9.6 - 2 ports: - "5432:5432" environment: - debug= false - db_user=wang - db_pass=yunfei - db_name=order volumes: - /srv/docker/postgresql:/var/lib/postgresql:z |
2.auth-server
2.1 oauth2服務配置
redis
用來存儲token
,服務重啟后,無需重新獲取token
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
@configuration @enableauthorizationserver public class authorizationserverconfig extends authorizationserverconfigureradapter { @autowired private authenticationmanager authenticationmanager; @autowired private redisconnectionfactory connectionfactory; @bean public redistokenstore tokenstore() { return new redistokenstore(connectionfactory); } @override public void configure(authorizationserverendpointsconfigurer endpoints) throws exception { endpoints .authenticationmanager(authenticationmanager) .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( "android" ) .scopes( "xx" ) //此處的scopes是無用的,可以隨意設置 .secret( "android" ) .authorizedgranttypes( "password" , "authorization_code" , "refresh_token" ) .and() .withclient( "webapp" ) .scopes( "xx" ) .authorizedgranttypes( "implicit" ); } } |
2.2 resource服務配置
auth-server
提供user信息,所以auth-server
也是一個resource server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@configuration @enableresourceserver public class resourceserverconfig extends resourceserverconfigureradapter { @override public void configure(httpsecurity http) throws exception { http .csrf().disable() .exceptionhandling() .authenticationentrypoint((request, response, authexception) -> response.senderror(httpservletresponse.sc_unauthorized)) .and() .authorizerequests() .anyrequest().authenticated() .and() .httpbasic(); } } |
1
2
3
4
5
6
7
8
|
@restcontroller public class usercontroller { @getmapping ( "/user" ) public principal user(principal user){ return user; } } |
2.3 安全配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
@configuration public class securityconfig extends websecurityconfigureradapter { @bean public userdetailsservice userdetailsservice(){ return new domainuserdetailsservice(); } @bean public passwordencoder passwordencoder() { return new bcryptpasswordencoder(); } @override protected void configure(authenticationmanagerbuilder auth) throws exception { auth .userdetailsservice(userdetailsservice()) .passwordencoder(passwordencoder()); } @bean public securityevaluationcontextextension securityevaluationcontextextension() { return new securityevaluationcontextextension(); } //不定義沒有password grant_type @override @bean public authenticationmanager authenticationmanagerbean() throws exception { return super .authenticationmanagerbean(); } } |
2.4 權限設計
采用用戶(sysuser)
角色(sysrole)
權限(sysauthotity)
設置,彼此之間的關系是多對多
。通過domainuserdetailsservice
加載用戶和權限。
2.5 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
spring: profiles: active: ${spring_profiles_active:dev} application: name: auth-server jpa: open-in-view: true database: postgresql show-sql: true hibernate: ddl-auto: update datasource: platform: postgres url: jdbc:postgresql: //192.168.1.140:5432/auth username: wang password: yunfei driver- class -name: org.postgresql.driver redis: host: 192.168 . 1.140 server: port: 9999 eureka: client: serviceurl: defaultzone: http: //${eureka.host:localhost}:${eureka.port:8761}/eureka/ logging.level.org.springframework.security: debug logging.leve.org.springframework: debug ##很重要 security: oauth2: resource: filter-order: 3 |
2.6 測試數據
data.sql
里初始化了兩個用戶admin
->role_admin
->query_demo
,wyf
->role_user
3.order-service
3.1 resource服務配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@configuration @enableresourceserver public class resourceserverconfig extends resourceserverconfigureradapter{ @override public void configure(httpsecurity http) throws exception { http .csrf().disable() .exceptionhandling() .authenticationentrypoint((request, response, authexception) -> response.senderror(httpservletresponse.sc_unauthorized)) .and() .authorizerequests() .anyrequest().authenticated() .and() .httpbasic(); } } |
3.2 用戶信息配置
order-service
是一個簡單的微服務,使用auth-server
進行認證授權,在它的配置文件指定用戶信息在auth-server
的地址即可:
1
2
3
4
5
6
|
security: oauth2: resource: id: order-service user-info-uri: http: //localhost:8080/uaa/user prefer-token-info: false |
3.3 權限測試控制器
具備authority
未query-demo
的才能訪問,即為admin
用戶
1
2
3
4
5
6
7
8
|
@restcontroller public class democontroller { @getmapping ( "/demo" ) @preauthorize ( "hasauthority('query-demo')" ) public string getdemo(){ return "good" ; } } |
4 api-gateway
api-gateway
在本例中有2個作用:
-
本身作為一個client,使用
implicit
- 作為外部app訪問的方向代理
4.1 關閉csrf并開啟oauth2 client支持
1
2
3
4
5
6
7
8
9
|
@configuration @enableoauth2sso public class securityconfig extends websecurityconfigureradapter{ @override protected void configure(httpsecurity http) throws exception { http.csrf().disable(); } } |
4.2 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
zuul: routes: uaa: path: /uaa/** sensitiveheaders: serviceid: auth-server order: path: /order/** sensitiveheaders: serviceid: order-service add-proxy-headers: true security: oauth2: client: access-token-uri: http: //localhost:8080/uaa/oauth/token user-authorization-uri: http: //localhost:8080/uaa/oauth/authorize client-id: webapp resource: user-info-uri: http: //localhost:8080/uaa/user prefer-token-info: false |
5 演示
5.1 客戶端調用
使用postman
向http://localhost:8080/uaa/oauth/token
發送請求獲得access_token
(admin用戶的如7f9b54d4-fd25-4a2c-a848-ddf8f119230b
)
admin用戶
wyf用戶
5.2 api-gateway中的webapp調用
暫時沒有做測試,下次補充。
6 源碼地址
https://github.com/wiselyman/uaa-zuul
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.wisely.top/2017/06/14/spring-cloud-oauth2-zuul/