Spring Security OAuth2:資源服務器實現


接着上一篇博客:https://www.cnblogs.com/wwjj4811/p/14504825.html

概述

資源服務器實際上就是對系統功能的增刪改查,比如:商品管理、訂單管理等資源,而在微服務架構中,而這每個資源實際上就是每一個微服務。當用戶請求某個微服務資源時,首先通過認證服務器進行認證與授權,通過后再才可訪問到對應資源。

實現的功能:

  1. 要讓他知道自己是資源服務器,系統知道這件事后,才會在前邊加一個過濾器去驗令牌(配置@EnableResourceServer 配置類)
  2. 要讓他知道自己是什么資源服務器(配置資源服務器ID) ,配置去哪里驗令牌,怎么驗令牌,要帶什么信息去驗
  3. 進行資源的安全配置,讓系統知道資源的每個訪問權限是什么

創建商品資源模塊

模塊名:cloud-oauth2-resource-product

依賴

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-oauth2-parent</artifactId>
        <groupId>com.wj</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-oauth2-resource-product</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.wj</groupId>
            <artifactId>cloud-oauth2-base</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Security、OAuth2 和JWT等 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <!-- 注冊到 Eureka
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
</project>

創建啟動類

啟動類com.wj.oauth2.ProductApplication

@SpringBootApplication
public class ProductApplication {

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

創建訪問資源

com.wj.oauth2.web.controller.ProductController

@RestController
@RequestMapping("/product")
public class ProductController {

    @GetMapping("/list")
    @PreAuthorize("hasAuthority('product:list')")
    public R list() {
        List<String> list = new ArrayList<>();
        list.add("huawei");
        list.add("vivo");
        list.add("oppo");
        return R.ok(list);
    }
}

配置資源服務器

創建com.wj.oauth2.resource.ResourceServerConfig類,繼承ResourceServerConfigurerAdapter類

@Configuration
// 標識為資源服務器, 所有發往當前服務的請求,都會去請求頭里找token,找不到或驗證不通過不允許訪問
@EnableResourceServer
//開啟方法級別權限控制
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    //配置當前資源服務器的ID
    private static final String RESOURCE_ID = "product-server";

    /**當前資源服務器的一些配置, 如資源服務器ID **/
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        // 配置當前資源服務器的ID, 會在認證服務器驗證(客戶端表的resources配置了就可以訪問這個服務)
        resources.resourceId(RESOURCE_ID)
            // 實現令牌服務, ResourceServerTokenServices實例
            .tokenServices(tokenService());
    }

    /**
     *  配置資源服務器如何驗證token有效性
     *  1. DefaultTokenServices
     *     如果認證服務器和資源服務器同一服務時,則直接采用此默認服務驗證即可
     *  2. RemoteTokenServices (當前采用這個)
     *     當認證服務器和資源服務器不是同一服務時, 要使用此服務去遠程認證服務器驗證
     * */
    @Bean
    public ResourceServerTokenServices tokenService() {
        // 資源服務器去遠程認證服務器驗證 token 是否有效
        RemoteTokenServices service = new RemoteTokenServices();
        // 請求認證服務器驗證URL,注意:默認這個端點是拒絕訪問的,要設置認證后可訪問
        service.setCheckTokenEndpointUrl("http://localhost:8090/auth/oauth/check_token");
        // 在認證服務器配置的客戶端id
        service.setClientId("wj-pc");
        // 在認證服務器配置的客戶端密碼
        service.setClientSecret("wj-secret");
        return service;
    }
}

修改認證服務器的CustomUserDetailsService類:添加指定權限

image-20210309134045866

測試

先用密碼認證模式獲取access_token

image-20210309132229410

然后請求http://localhost:8080/product/list,

這里請求頭需要加上Authorization,值是Bearer 加上空格再加上認證服務器獲取到的access_token

image-20210309132259594

點擊發送,我們就可以獲取到指定資源了。

控制令牌權限和授權規則

  1. 資源服務器通過ResourceServerConfigurerAdapter#configure(HttpSecurity http)指定授權規則。
  2. 禁用Session,因為是基於 token 認證,所以不需要 HttpSession 了指定資源的授權規則,與 SpringSecurity 中的指定方式一樣
  3. 用#oauth2表達式控制令牌范圍 scope,如果令牌的沒有對應scope權限,則對應資源不允許訪問

ResourceServerConfig中重寫父類方法:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
        //不創建session
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        //資源授權規則
        .authorizeRequests().antMatchers("/product/**").hasAuthority("product")
        //所有的請求對應訪問的用戶都要有all范圍的權限
        .antMatchers("/**").access("#oauth2.hasScope('all')");
}

測試

我們先將scope改掉

image-20210309134541588

image-20210309134555573

再次訪問,就會提示scope的錯誤

image-20210309134612208


免責聲明!

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



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