網關安全(二)-OAuth2協議簡介與認證服務器搭建


1、OAuth2協議中的角色流程概要介紹

OAuth2協議主要使用來認證和授權的,我們先來看一下OAuth2協議中的角色

  1.1、用戶:真正的人,大家都有可能是某一個服務的用戶。

  1.2、客戶端應用:Web或手機App,直接跟用戶打交道的。通過客戶端應用發http請求,訪問服務。

  1.3、認證服務器:作用就是認證,驗證用戶身份發出令牌。

  1.4、資源服務器:在這里代表各個微服務。一個認證服務器可以對應多個資源服務器。

  大概的流程是:用戶直接訪問客戶端應用,客戶端首先要去認證服務器認證,驗證要訪問微服務用戶的真實性,認證服務器確認用戶身份后,會發出一個代表用戶身份的令牌給客戶端應用,客戶端應用就會拿着令牌去訪問資源服務器(我們的微服務),資源服務器會去認證服務器驗證這個令牌是誰。

2、部分角色准備

  2.1、用戶,就是我們自己。

  2.2、客戶端應用:http請求工具,可以是Restlet Client、Postman等。

  2.3、資源服務器,我們准備兩個簡單的微服務,一個訂單服務,一個價格服務,訂單服務調用價格服務獲取價格。

    2.3.1、訂單服務,端口9080

    2.3.2、價格服務,端口9070

3、搭建認證服務器

  3.1、項目結構

   3.2、pom.xml導入spring-cloud-starter-oauth2依賴

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
    </dependencies>

  3.3、OAuth2AuthServerConfig,認證服務器配置

/**
 * OAuth2認證服務器配置類
 * 需要繼承AuthorizationServerConfigurerAdapter類,覆蓋里面三個configure方法
 * 並添加@EnableAuthorizationServer注解,指定當前應用做為認證服務器
 *
 * @author caofanqi
 * @date 2020/1/31 18:04
 */
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter {


    @Resource
    private AuthenticationManager authenticationManager;


    /**
     * 配置授權服務器的安全性
     * checkTokenAccess:驗證令牌需要什么條件,isAuthenticated():需要經過身份認證。
     * 此處的passwordEncoders是為client secrets配置的。
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()").passwordEncoder(new BCryptPasswordEncoder());
    }

    /**
     * 配置客戶端服務
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                //配置在內存中
                .inMemory()
                //客戶端應用的用戶名
                .withClient("webApp")
                //客戶端應用加密過的密碼
                .secret(new BCryptPasswordEncoder().encode("123456"))
                //orderApp可以獲取所有的權限集合,用於做ACL的權限控制
                .scopes("read", "write")
                //發出去令牌的有效期,單位秒
                .accessTokenValiditySeconds(3600)
                //可以訪問哪些資源服務器
                .resourceIds("order-server")
                //授權的方式
                .authorizedGrantTypes("password")
                .and()
                //訂單服務要訪問資源服務器驗證令牌,所以也需要配置相關信息
                .withClient("orderService")
                .secret(new BCryptPasswordEncoder().encode("123456"))
                .scopes("read", "write")
                .accessTokenValiditySeconds(3600)
                .resourceIds("order-server")
                .authorizedGrantTypes("password");

    }

    /**
     * 配置授權服務器終端的非安全特征
     * authenticationManager 校驗用戶信息是否合法
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }

}

  3.4、WebSecurityConfig,安全配置

/**
 * WebSecurity安全配置
 *
 * @author caofanqi
 * @date 2020/1/31 22:48
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Resource
    private UserDetailsService userDetailsService;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * AuthenticationManagerBuilder可以幫助我們構建出一個AuthenticationManager,需要UserDetailsService和PasswordEncoder
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }


    /**
     * 將AuthenticationManager暴露成Bean
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}

  3.5、UserDetailsService

/**
 * 查詢用戶信息
 * @author caofanqi
 * @date 2020/2/1 3:41
 */
@Component
public class UserDetailsServiceImpl implements UserDetailsService {


    /**
     *  此處為了簡便,沒有連接數據庫,不管什么用戶名,只要密碼是123456就會通過驗證
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return User.withUsername(username)
                .password(new BCryptPasswordEncoder().encode("123456"))
                .authorities("ROLE_ADMIN").build();
    }

}

  3.6、啟動項目,端口9020,看控制台有三個路徑,/oauth/token獲取token,/oauth/token_key,/oauth/check_token用於校驗token

   3.7、測試密碼模式獲取令牌

    3.7.1、請求路徑:http://127.0.0.1:9020/oauth/token

    3.7.2、使用httpBasic添加客戶端認證信息

    3.7.3、表單添加用戶信息,username(用戶名)、password(密碼)、grant_type(授權模式)、scope(權限范圍)

  3.7.4、返回值,access_token(令牌)、token_type(令牌類型)、expires_in(有效期剩余時間)、scope(權限范圍)。

 

項目源碼:https://github.com/caofanqi/study-security/tree/dev-AuthorizationServer


免責聲明!

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



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