基於spring-security-oauth2認證授權服務介紹與使用(一)

1、springCloud Oauth2 基本介紹

OAuth:OAuth(開放授權)是一個開放標準,允許用戶授權第三方網站訪問他們存儲在另外的服務提供者上的信息,而不需要將用戶名和密碼提供給第三方網站或分享他們數據的所有內容。
在Spring Cloud需要使用oauth2來實現多個微服務的統一認證授權,通過向OAUTH服務發送某個類型的grant type進行集中認證和授權,從而獲得access_token,而這個token是受其他微服務信任的,我們在後續的訪問可以通過access_token來進行,從而實現了微服務的統一認證授權。
客戶端根據約定的ClientID、ClientSecret、Scope來從Access Token URL地址獲取AccessToken,並經過AuthURL認證,用得到的AccessToken來訪問其他資源接口。
Spring Cloud oauth2 需要依賴Spring security

2、Oauth2 角色劃分

  1. Resource Sever --> 被授權訪問的資源
  2. Authorization Server --> Oauth2認證授權中心
  3. Resource Owner --> 用戶
  4. Client --> 使用API 的客戶端(比如:Android、IOS、web app…)

3、Oauth2的四種授權方式

  1. 授權碼模式(authorization code)用在客戶端與服務端應用之間授權
  2. 簡化模式(implicit)用在移動ap或者web app(這些app是在用戶設備上的,如在手機上調用微信來認證授權)
  3. 密碼模式(resource owner password credentials)應用直接都是受信任的
  4. 客戶端模式(client credentials)用在應用API訪問

4、Oauth2環境搭建

目錄結構及項目地址:spring-security-oauth2
在這裏插入圖片描述

4.1、搭建 spring-security-oauth2 項目[pom]

4.1.1、pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
 </parent>

4.2、搭建oauth2-server 認證授權中心服務

4.2.1、pom.xml

<dependencies>
        <!-- SpringBoot整合Web組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- springboot整合freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

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

    </dependencies>

    <!-- 管理依賴 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 注意: 這裏必須要添加, 否者各種依賴有問題 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

4.2.2、application.yml

server:
  port: 9090

4.2.3、配置信息

package com.redmaple.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * @Description 配置授權中心信息
 * @Author redMaple-gi
 * @Date 2020/6/19 13:39
 * @Version 1.0
 */
@Configuration
@EnableAuthorizationServer  //開啓oauth2認證授權中心服務
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    // accessToken過期時間-1小時
    private static int accessTokenValiditySeconds = 3600;
    // accessToken的刷新時間
    private static int refreshTokenValiditySeconds = 3600;

    /**
     * 應該讀取數據庫,先固定寫
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("client_1")
                .secret(passwordEncoder().encode("123456"))
//                .authorizedGrantTypes("authorization_code","refresh_token")     //授權碼模式
//                .authorizedGrantTypes("password")   //密碼模式
//                .authorizedGrantTypes("client_credentials")   //客戶端模式
                //混合模式
                .authorizedGrantTypes("authorization_code","password","refresh_token")
                //回調地址
                .redirectUris("http://www.baidu.com")
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds)
                .scopes("all");

    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允許表單認證
        security.allowFormAuthenticationForClients();
        // 允許check_token 訪問
        security.checkTokenAccess("permitAll()");
    }

    /**
     * 設置token類型
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager())
            .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
    }

    @Bean
    public AuthenticationManager authenticationManager(){
        AuthenticationManager authenticationManager = new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                return daoAuthenticationProvider().authenticate(authentication);
            }
        };
        return authenticationManager;
    }


    @Bean
    public AuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }

    /**
     * 這裏是用戶名和密碼,需要從數據庫讀取
     * 測試先固定
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("redmaple")
                .password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER").build()
        );
        userDetailsService.createUser(User.withUsername("admin")
                .password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER").build()
        );
        return userDetailsService;
    }

    /**
     * 加密方式
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

這裏必須要加上SecurityConfig 配置文件,否則會報錯 User must be authenticated with Spring Security before authorization can be completed 錯誤,因爲訪問請求沒有放行。

package com.redmaple.config;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.stereotype.Component;

/**
 * @Description 訪問接口報錯
 * User must be authenticated with Spring Security before authorization can be completed.
 * 需要開發權限,允許所有的接口訪問進來
 * @Author redMaple-gi
 * @Date 2020/6/19 14:13
 * @Version 1.0
 */
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**")
                .fullyAuthenticated().and().formLogin();
    }
}

4.2.4、啓動服務

@SpringBootApplication
public class AppOauth2Server {
    public static void main(String[] args) {
        SpringApplication.run(AppOauth2Server.class,args);
    }
}

4.3、搭建oauth2-resources-order 普通微服務,驗證授權服務

4.3.1、pom.xml

<dependencies>
        <!-- SpringBoot整合Web組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- springboot整合freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

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

    </dependencies>

    <!-- 管理依賴 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 注意: 這裏必須要添加, 否者各種依賴有問題 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

4.3.2、application.yml

server:
  port: 9091
logging:
  level:
    org.springframework.security: DEBUG

security:
  oauth2:
    resource:
      ## 從認證授權中心上驗證token
      token-info-uri: http://localhost:9090/oauth/check_token
      prefer-token-info: true
    client:
      access-token-uri: http://localhost:9090/oauth/token
      user-authorization-uri: http://localhost:9090/oauth/authorize
      ## appid
      client-id: client_1
      ## appSecret
      client-secret: 123456

4.3.3、配置信息

package com.redmaple.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

/**
 * @Description 配置攔截設置
 * @Author redMaple-gi
 * @Date 2020/6/19 14:51
 * @Version 1.0
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 對接口/api/order/** 進行攔截
        http.authorizeRequests().antMatchers("/api/order/**").authenticated();
    }
}

4.3.4、認證授權接口

package com.redmaple.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description
 * @Author redMaple-gi
 * @Date 2020/6/19 14:54
 * @Version 1.0
 */
@RestController
@RequestMapping("/api/order")
public class OrderController {

    @GetMapping("/getOrder")
    public String getOrder(){
        System.out.println("This is my first time I've intercepted a request with OAuth2!");
        return "This is my first time I've intercepted a request with OAuth2!";
    }
}

4.3.5、啓動服務

package com.redmaple;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;

/**
 * @Description
 * @Author redMaple-gi
 * @Date 2020/6/19 14:50
 * @Version 1.0
 */
@SpringBootApplication
@EnableOAuth2Sso
public class AppOauth2Order {
    public static void main(String[] args) {
        SpringApplication.run(AppOauth2Order.class, args);
    }
}

5、如何測試認證授權中心服務和訪問資源服務器

接下來就是測試如何使用oauth2-server和oauth2-resources-order服務
下一篇:基於spring-security-oauth2認證授權服務介紹與使用(二)
項目地址:https://gitee.com/kuiwang2/spring-security-oauth2.git
參考地址:螞蟻課堂

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