SpringCloudAlibaba+Zuul+OAuth2 (一) 搭建認證微服務

開發背景什麼的我就不介紹了官網介紹:https://spring.io/guides/tutorials/spring-boot-oauth2/  既然大家需要用到這個技術 直接擼代碼吧!!!

1.創建maven springboot項目 添加相關依賴 採用最新的版本(相關依賴版本如下)

<!--spring-boot 版本-->
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.2.5.RELEASE</version>
</parent>

<!--spring-cloud  spring cloud alibaba版本-->

<dependencyManagement>
        <dependencies>
            <!--整合spring cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--整合spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>


<!--整合oauth2-->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

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

2.創建oauth2 認證服務器配置類 

/**
 *
 * @Description Authorization配置
 * @Date 2020/6/24 11:36
 * @Author Jax
 */
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthServiceConfig extends AuthorizationServerConfigurerAdapter {


    @Autowired
    private PasswordEncoder passwordEncoder;

   /**
     * 這裏先把服務寫到內存裏面 後續配置到mysql
     * 配置client服務詳情(也就說有哪些服務可以來向我申請令牌)
     * see:org.springframework.security.oauth2.provider.authentication
     * 我這裏假設我現在有一個遊戲微服務game_client  一個網關微服務gateway_client
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("game_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)//token的失效時間 單位秒
                .resourceIds("game-service")
                .scopes("read", "write")//控制發出去的服務令牌權限
                .authorizedGrantTypes("password")//授權方式
                .and()
                .withClient("gateway_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)
                .resourceIds("gateway")
                .scopes("read", "write")
                .authorizedGrantTypes("password");
    }


//OAuth2爲我們提供了四種授權方式:
//1、授權碼模式(authorization code)
     //授權碼相對其他三種來說是功能比較完整、流程最安全嚴謹的授權方式,通過客戶端的後臺服務器與服務提供商的認證服務器交互來完成
//2、簡化模式(implicit)
     //這種模式不通過服務器端程序來完成,直接由瀏覽器發送請求獲取令牌,令牌是完全暴露在瀏覽器中的,這種模式極力不推崇
//3、密碼模式(resource owner password credentials)
     //密碼模式也是比較常用到的一種,客戶端向授權服務器提供用戶名、密碼然後得到授權令牌。這種模式不過有種弊端,我們的客戶端需要存儲用戶輸入的密碼,但是對於用戶來說信任度不高的平臺是不可能讓他們輸入密碼的
//4、客戶端模式(client credentials)
     //客戶端模式是客戶端以自己的名義去授權服務器申請授權令牌,並不是完全意義上的授權。

}

 3.需要配置認證服務器知道可以讓哪些用戶來訪問我 即authenticationManager配置

/**
 *
 * @Description Authorization配置
 * @Date 2020/6/24 11:36
 * @Author Jax
 */
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthServiceConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    


   /**
     * 這裏先把服務寫到內存裏面 生產環境肯定是不行的 需要配置mysql參考我下面的配置
     * 建議先把流程走通 再倒回來 配置mysql持久化
     * 配置client服務詳情(也就說有哪些服務可以來向我申請令牌)
     * see:org.springframework.security.oauth2.provider.authentication
     * 我這裏假設我現在有一個遊戲微服務game_client  一個網關微服務gateway_client
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("game_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)
                .resourceIds("gateway", "game-service")
                .scopes("read", "write")
                .authorizedGrantTypes("password")
                .and()
                .withClient("gateway_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)
                .resourceIds("gateway", "game-service")
                .scopes("read", "write")
                .authorizedGrantTypes("password");
    }


    /**
     * 配置哪些可以訪問認證服務器
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager); //authenticationManager校驗傳遞進來的用戶是否合法
    }


}
  1. 上面配置是爲了測試 放在了內存裏 然而這樣在生產環境肯定是不行的!因爲我們要對客戶開放註冊Client!我們要實現Client的註冊,動態的加載到Oauth服務中。所以要實現Client的持久化,這裏我們使用Mysql 建議直接先跳過這裏的步驟 先把流程走通 再倒回來 配置mysql持久化!!!
  2. pom文件添加依賴

    <!--整合jdbc 實現服務數據持久化-->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- mysql connector -->
    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
    </dependency>

     

  3. 導入sql腳本(這裏使用mysql)
    /*
     Navicat Premium Data Transfer
    
     Source Server         : 192.168.2.230
     Source Server Type    : MySQL
     Source Server Version : 50725
     Source Host           : 192.168.2.230:3306
     Source Schema         : oauth
    
     Target Server Type    : MySQL
     Target Server Version : 50725
     File Encoding         : 65001
    
     Date: 02/07/2020 11:44:17
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for authority
    -- ----------------------------
    DROP TABLE IF EXISTS `authority`;
    CREATE TABLE `authority`  (
      `id` bigint(11) NOT NULL COMMENT '權限id',
      `authority` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '權限',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for credentials
    -- ----------------------------
    DROP TABLE IF EXISTS `credentials`;
    CREATE TABLE `credentials`  (
      `id` bigint(11) NOT NULL COMMENT '憑證id',
      `enabled` tinyint(1) NOT NULL COMMENT '是否可用',
      `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用戶名',
      `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密碼',
      `version` int(11) NULL DEFAULT NULL COMMENT '版本號',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for credentials_authorities
    -- ----------------------------
    DROP TABLE IF EXISTS `credentials_authorities`;
    CREATE TABLE `credentials_authorities`  (
      `credentials_id` bigint(20) NOT NULL COMMENT '憑證id',
      `authorities_id` bigint(20) NOT NULL COMMENT '權限id'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_access_token
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_access_token`;
    CREATE TABLE `oauth_access_token`  (
      `token_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密的access_token的值',
      `token` longblob NULL COMMENT 'OAuth2AccessToken.java對象序列化後的二進制數據',
      `authentication_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密過的username,client_id,scope',
      `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登錄的用戶名',
      `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端ID',
      `authentication` longblob NULL COMMENT 'OAuth2Authentication.java對象序列化後的二進制數據',
      `refresh_token` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密的refresh_token的值'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_approvals
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_approvals`;
    CREATE TABLE `oauth_approvals`  (
      `userId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登錄的用戶名',
      `clientId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端ID',
      `scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '申請的權限範圍',
      `status` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '狀態(Approve或Deny)',
      `expiresAt` datetime(0) NULL DEFAULT NULL COMMENT '過期時間',
      `lastModifiedAt` datetime(0) NULL DEFAULT NULL COMMENT '最終修改時間'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_client_details
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_client_details`;
    CREATE TABLE `oauth_client_details`  (
      `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客戶端ID',
      `resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '資源ID集合,多個資源時用逗號(,)分隔',
      `client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端密匙',
      `scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端申請的權限範圍',
      `authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端支持的grant_type',
      `web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '重定向URI',
      `authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端所擁有的Spring Security的權限值,多個用逗號(,)分隔',
      `access_token_validity` int(11) NULL DEFAULT NULL COMMENT '訪問令牌有效時間值(單位:秒)',
      `refresh_token_validity` int(11) NULL DEFAULT NULL COMMENT '更新令牌有效時間值(單位:秒)',
      `additional_information` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '預留字段',
      `autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用戶是否自動Approval操作'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_client_token
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_client_token`;
    CREATE TABLE `oauth_client_token`  (
      `token_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密的access_token值',
      `token` longblob NULL COMMENT 'OAuth2AccessToken.java對象序列化後的二進制數據',
      `authentication_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密過的username,client_id,scope',
      `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登錄的用戶名',
      `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客戶端ID'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_code
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_code`;
    CREATE TABLE `oauth_code`  (
      `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '授權碼(未加密)',
      `authentication` varbinary(255) NULL DEFAULT NULL COMMENT 'AuthorizationRequestHolder.java對象序列化後的二進制數據'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for oauth_refresh_token
    -- ----------------------------
    DROP TABLE IF EXISTS `oauth_refresh_token`;
    CREATE TABLE `oauth_refresh_token`  (
      `token_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '加密過的refresh_token的值',
      `token` longblob NULL COMMENT 'OAuth2RefreshToken.java對象序列化後的二進制數據 ',
      `authentication` longblob NULL COMMENT 'OAuth2Authentication.java對象序列化後的二進制數據'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for sys_user
    -- ----------------------------
    DROP TABLE IF EXISTS `sys_user`;
    CREATE TABLE `sys_user`  (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用戶名',
      `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密碼',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶信息表' ROW_FORMAT = Dynamic;
    
    SET FOREIGN_KEY_CHECKS = 1;
    

     

  4. 插入2條測試數據 即上面配置在內存的數據 密碼是123456 我這裏用passwordEncoder編譯了一下
    public static void main(String[] args) {
            System.out.println(new BCryptPasswordEncoder().encode("123456"));
        }
    
    
    
    INSERT INTO `oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('game_client', 'game-service,gateway', '$2a$10$HT1fF.8WhP08YblPWphCMeuzJM7AP68LR86uC/kX9tbXIHOxBbkMW', 'read,write', 'password,client_credentials', 'http://127.0.0.1', 'ROLE_PROJECT_ADMIN', 7200, 1800, NULL, 'true');
    INSERT INTO `oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('gateway_client', 'gateway', '$2a$10$HT1fF.8WhP08YblPWphCMeuzJM7AP68LR86uC/kX9tbXIHOxBbkMW', 'read,write', 'password', 'http://127.0.0.1', 'ROLE_PROJECT_ADMIN', 7200, 1800, NULL, 'true');
    

     

  5. 編寫yml配置
    spring:  
        application:
          name: auth
        datasource:
            url: jdbc:mysql://192.168.2.130:3306/你的數據庫?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=UTC
            username: root
            password: ****
            driver-class-name: com.mysql.cj.jdbc.Driver
  6. 編寫Oauth2AuthServiceConfig配置
    /**
     *
     * @Description Authorization配置
     * @Date 2020/6/24 11:36
     * @Author Jax
     */
    @Configuration
    @EnableAuthorizationServer
    public class OAuth2AuthServiceConfig extends AuthorizationServerConfigurerAdapter {
    
        //注入數據源
        @Autowired
        private DataSource dataSource;
    
       /**
         * 這裏配置到mysql 數據跟寫入內存一樣的 不影響後面的測試
         * 配置client服務詳情(也就說有哪些服務可以來向我申請令牌)
         * see:org.springframework.security.oauth2.provider.authentication
         * 我這裏假設我現在有一個遊戲微服務game_client  一個網關微服務gateway_client
         * @param clients
         * @throws Exception
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
        }
    
        //需要把token的信息放進mysql 生成的token 存放的表:oauth_access_token
        @Bean
        public TokenStore jdbcTokenStore() {
            //使用數據庫來操作token
            return new JdbcTokenStore(dataSource);
        }
    
     /**
         * 配置哪些可以訪問認證服務器
         *
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                     .tokenStore(jdbcTokenStore())//需要告訴我們的服務器需要用JdbcTokenStore來存儲我們的token
                     .authenticationManager(authenticationManager); //authenticationManager校驗傳遞進來的用戶是否合法
        }

     

                                                                                 至此mysql 持久化配置+管理token完成!!!

  • 翻外篇 如果想使用JWT來生成 管理token 應該怎麼來改造 建議先把第一遍流程走通再倒回來看這些配置!!!
    /**
     *
     * @Description Authorization配置
     * @Date 2020/6/24 11:36
     * @Author Jax
     */
    @Configuration
    @EnableAuthorizationServer
    public class OAuth2AuthServiceConfig extends AuthorizationServerConfigurerAdapter {
    
        //注入數據源
        @Autowired
        private DataSource dataSource;
    
       /**
         * 這裏配置到mysql
         * 配置client服務詳情(也就說有哪些服務可以來向我申請令牌)
         * see:org.springframework.security.oauth2.provider.authentication
         * 我這裏假設我現在有一個遊戲微服務game_client  一個網關微服務gateway_client
         * @param clients
         * @throws Exception
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
        }
    
        //把之前JdbdTokenStore 改成JwtTokenStore 就可以了
        @Bean
        public TokenStore jwtTokenStore() {
            //使用Jwt操作token
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    
    
        /**
        * 這裏必須要聲明成 @Bean public 才能暴露TokenKeyEndpoint這個url
        * TokenKeyEndpoint這個端點得作用是暴露SigningKey 
        **/
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            //推薦使用證書作爲生成token的密鑰
            //KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("aa.key"),"123456".toCharArray());
            //converter.setKeyPair(keyStoreKeyFactory.getKeyPair("aa"));
            converter.setSigningKey("abcdefg");//這裏採用abcdefg作爲生成密鑰的key
            return converter;
        }
    
     /**
         * 配置哪些可以訪問認證服務器
         *
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                     .tokenEnhancer(jwtAccessTokenConverter())//配置token方式
                     .tokenStore(jwtTokenStore())//需要告訴我們的服務器需要用jwtTokenStore來存儲我們的token
                     .authenticationManager(authenticationManager); //authenticationManager校驗傳遞進來的用戶是否合法
        }
    
    
        /**
         * 配置驗證令牌的條件(即滿足什麼樣的條件才能找我驗證令牌 不是隨便拿token也來驗證)
         * 這裏都先做一個最基本的配置
         *
         * @param security
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security
                    .tokenKeyAccess("isAuthenticated()")    //暴露signingKey 經過認證之後服務才能拿到這個簽名的key
                    .checkTokenAccess("isAuthenticated()");//檢驗服務驗證的規則 必須是經過驗證的 用戶名 密碼 就是上面所配置的 game_client 123456 ..... 我纔給你驗證令牌
        }
    
    
    
    
    }

 

                                                                         OK改造成JWT 生成token 完成!

4.寫好前面的配置 這個時候我們需要來配置低3步中注入的AuthenticationManager  PasswordEncoder 

/**
 * @Description 配置認證服務器WEB配置
 * @Date 2020/6/24 11:49
 * @Author Jax
 */
@Configuration
@EnableWebSecurity
public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //根據用戶名獲取用戶詳細信息 接下來 我們需要來實現這個方法 (第5步)
    @Autowired
    private UserDetailsService userDetailsService;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

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

5.實現UserDetailsService這個方法 編寫代碼

/**
 * @Description 獲取用戶信息
 * @Date 2020/6/24 12:31
 * @Author Jax
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //TODO 需要去數據庫查詢當前用戶信息 這裏方便測試 採用org.springframework.security.core.userdetails 來構建一個用戶
        return User.withUsername(username)  //構建一個用戶所必須的3個條件 用戶名 密碼 權限 
                .password(passwordEncoder.encode("123456"))
                .authorities("ROLE_ADMIN")
                .build();
    }
}

6.完成上述步驟 合法的應用信息(3步) 合法的用戶信息 現在我們都配置好了 接下來我們應該配置 微服務驗證令牌的相關配置了 接着上面第3步 繼續寫代碼

/**
 *
 * @Description Authorization配置
 * @Date 2020/6/24 11:36
 * @Author Jax
 */
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthServiceConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    


   /**
     * 這裏先把服務寫到內存裏面
     * 配置client服務詳情(也就說有哪些服務可以來向我申請令牌)
     * authorizedGrantTypes類型支持https://www.cnblogs.com/strugglepcx/p/5139013.html
     * see:org.springframework.security.oauth2.provider.authentication
     * 我這裏假設我現在有一個遊戲微服務game_client  一個網關微服務gateway_client
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("game_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)
                .resourceIds("gateway", "game-service")
                .scopes("read", "write")
                .authorizedGrantTypes("password")
                .and()
                .withClient("gateway_client")
                .secret(passwordEncoder.encode("123456"))
                .accessTokenValiditySeconds(3600)
                .resourceIds("gateway", "game-service")
                .scopes("read", "write")
                .authorizedGrantTypes("password");
    }


    /**
     * 配置哪些可以訪問認證服務器
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager); //authenticationManager校驗傳遞進來的用戶是否合法
    }


    /**
     * 配置驗證令牌的條件(即滿足什麼樣的條件才能找我驗證令牌 不是隨便拿token也來驗證)
     * 這裏都先做一個最基本的配置
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");//檢驗服務驗證的規則 必須是經過驗證的 用戶名 密碼 就是上面所配置的 game_client 123456 ..... 我纔給你驗證令牌
    }



}

7.啓動OAuth 微服務 使用postman訪問localhost:你的端口/oauth/token 進行測試 獲取token

返回結果如下 

OK SpringCloudAlibaba+Zuul+OAuth2 (一) 搭建認證微服務 完成!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章