Spring Cloud下基於OAUTH2認證授權的實現


 

GitHub(spring -boot 2.0.0):https://github.com/bigben0123/uaa-zuul
示例(spring -boot 2.0.0): https://github.com/bigben0123/sample-spring-oauth2-microservices (講解:https://piotrminkowski.wordpress.com/2017/12/01/part-2-microservices-security-with-oauth2/)

 

 

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

 格式正常地址:Spring Cloud下基於OAUTH2認證授權的實現包含源碼

本示例提供了四大部分:

  • 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在服務器上啟動PostgresRedis

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.

@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

@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();
    }
}

@RestController
public class UserController {

    @GetMapping("/user")
    public Principal user(Principal user){
        return user;
    }
}

2.3 安全配置

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

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服務配置

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

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

3.3 權限測試控制器

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

@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支持

@Configuration
@EnableOAuth2Sso
public 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: 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


http://www.360doc.com/content/17/0728/14/16915_674776055.shtml

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM