Spring Cloud下基於OAUTH2認證授權的實現樣本,cloudoauth2

來源:互聯網
上載者:User

Spring Cloud下基於OAUTH2認證授權的實現樣本,cloudoauth2

Spring Cloud需要使用OAUTH2來實現多個微服務的統一認證授權,通過向OAUTH服務發送某個類型的grant type進行集中認證和授權,從而獲得access_token,而這個token是受其他微服務信任的,我們在後續的訪問可以通過access_token來進行,從而實現了微服務的統一認證授權。

本樣本提供了四大部分:

  1. discovery-service:服務註冊和發現的基本模組
  2. auth-server:OAUTH2認證授權中心
  3. order-service:普通微服務,用來驗證認證和授權
  4. api-gateway:邊界網關(所有微服務都在它之後)

OAUTH2中的角色:

  1. Resource Server:被授權訪問的資源
  2. Authotization Server:OAUTH2認證授權中心
  3. Resource Owner: 使用者
  4. Client:使用API的用戶端(如Android 、IOS、web app)

Grant Type:

  1. Authorization Code:用在服務端應用之間
  2. Implicit:用在移動app或者web app(這些app是在使用者的裝置上的,如在手機上調起來進行認證授權)
  3. Resource Owner Password Credentials(password):應用直接都是受信任的(都是由一家公司開發的,本例子使用
  4. Client Credentials:用在應用API訪問。

1.基礎環境

使用Postgres作為賬戶儲存,Redis作為Token儲存,使用docker-compose在伺服器上啟動PostgresRedis

Redis: image: sameersbn/redis:latest ports: - "6379:6379" volumes: - /srv/docker/redis:/var/lib/redis:Z restart: alwaysPostgreSQL: 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.

@Configuration@EnableAuthorizationServerpublic 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

@Configuration@EnableResourceServerpublic 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(); }}
@RestControllerpublic class UserController { @GetMapping("/user") public Principal user(Principal user){  return user; }}

2.3 安全配置

@Configurationpublic 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 配置

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.140server: port: 9999eureka: client: serviceUrl:  defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/logging.level.org.springframework.security: DEBUGlogging.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服務配置

@Configuration@EnableResourceServerpublic 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的地址即可:

security: oauth2: resource:  id: order-service  user-info-uri: http://localhost:8080/uaa/user  prefer-token-info: false

3.3 許可權測試控制器

具備authorityquery-demo的才能訪問,即為admin使用者

@RestControllerpublic class DemoController { @GetMapping("/demo") @PreAuthorize("hasAuthority('query-demo')") public String getDemo(){  return "good"; }}

4 api-gateway

api-gateway在本例中有2個作用:

  1. 本身作為一個client,使用implicit
  2. 作為外部app訪問的方向代理

4.1 關閉csrf並開啟Oauth2 client支援

@Configuration@EnableOAuth2Ssopublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception {  http.csrf().disable(); }}

4.2 配置

zuul: routes: uaa:  path: /uaa/**  sensitiveHeaders:  serviceId: auth-server order:  path: /order/**  sensitiveHeaders:  serviceId: order-service add-proxy-headers: truesecurity: 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 用戶端調用

使用Postmanhttp://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

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.