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