(八)Spring Security (spring-cloud-starter-oauth2)应用详解------资源服务------密码模式

前提:在看完这一篇文章的基础上再进行本篇文章的开发
(七)Spring Security (spring-cloud-starter-oauth2)应用详解------认证授权服务------授权码模式和密码模式

创建 order 资源服务器配置

依赖如下:

<?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>spring-cloud-starter-oauth2</artifactId>
        <groupId>org.cyj</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</artifactId>

    <dependencies>
        <!--spring boot 相关-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--spring cloud oauth2 相关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.security.oauth.boot</groupId>
                    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--springboot 2.1.3 版本 可能不兼容 spring-security-oauth2-autoconfigure:2.1.0.M4 低版本吧
        所以我在上边排除spring-security-oauth2-autoconfigure 依赖-->
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <!--其他 依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

工程结构如下:
在这里插入图片描述

代码编写

配置文件
application.properties:

spring.application.name=order
server.port=8081
server.servlet.context-path=/order

启动类

package com.cyj.security.oauth2.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @Program: Spring-Security-OAuth2
 * @Description:
 * @Author C_Y_J
 * @Create: 2021-01-31 14:14
 **/
@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

controller

package com.cyj.security.oauth2.order.controller;

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

/**
 * @Program: Spring-Security-OAuth2
 * @Description:
 * @Author C_Y_J
 * @Create: 2021-01-30 23:21
 **/
@RestController
@RequestMapping("/r")
public class OrderController {

    @GetMapping(value = "/r1")
    public String r1() {
        return "张三的个人信息";
    }
}

**WebSecurityConfig **

package com.cyj.security.oauth2.order.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @Program: Spring-Security-OAuth2
 * @Description:
 * @Author C_Y_J
 * @Create: 2021-01-31 14:06
 **/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 安全拦截机制(最重要)
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                //所有/r/**的请求必须认证通过
                .antMatchers("/r/**").authenticated()
                //除了/r/**,其它的请求可以访问
                .anyRequest().permitAll();
    }
}

====================================================================

资源服务器配置

@EnableResourceServer 注解到一个 @Configuration 配置类上,并且必须使用 ResourceServerConfigurer 这个配置对象来进行配置(可以选择继承自 ResourceServerConfigurerAdapter 然后覆写其中的方法,参数就是这个对象的实例),下面是一些可以配置的属性:

ResourceServerSecurityConfigurer中主要包括:

tokenServices:ResourceServerTokenServices 类的实例,用来实现令牌服务。
tokenStore:TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选
resourceId:这个资源服务的ID,这个属性是可选的,但是推荐设置并在授权服务中进行验证。
其他的拓展属性例如 tokenExtractor 令牌提取器用来提取请求中的令牌。

package com.cyj.security.oauth2.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;

/**
 * @Program: Spring-Security-OAuth2
 * @Description:
 * @Author C_Y_J
 * @Create: 2021-01-30 23:23
 **/
@Configuration
@EnableResourceServer //自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {

    /**
     * 客户端访问的资源列表
     */
    public static final String RESOURCE_ID = "res1";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                //客户端访问的资源列表
                .resourceId(RESOURCE_ID)
                //验证令牌的服务
                .tokenServices(tokenService())
                .stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/**").access("#oauth2.hasScope('all')");
        http
                // 关闭 csrf
                .csrf().disable()
                //不创建session不使用session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

}

到这里,有人会发现,代码里有个地方爆红,这就是接下来要讲的内容 验证token
在这里插入图片描述

验证token

ResourceServerTokenServices 是组成授权服务的另一半,如果你的认证授权服务和资源服务在同一个应用程序上的话,你可以使用 DefaultTokenServices ,这样的话,你就不用考虑关于实现所有必要的接口的一致性问题。如果你的资源服务器是分离开的,那么你就必须要确保能够有匹配认证授权服务提供的 ResourceServerTokenServices,它知道如何对令牌进行解码。

令牌解析方法: 使用 DefaultTokenServices 在资源服务器本地配置令牌存储、解码、解析方式 使用
RemoteTokenServices 资源服务器通过 HTTP 请求来解码令牌,每次都请求认证授权服务器端点 /oauth/check_token

使用认证授权服务的 /oauth/check_token 端点,你需要在认证授权服务将这个端点暴露出去,以便资源服务可以进行访问,这里在上一篇文章中 auth认证授权服务 配置中已经提到了。
在这里插入图片描述
所以在 order 服务中 ResouceServerConfig 中添加代码

  /**
     * 资源服务令牌解析服务
     *
     * @return
     */
    @Bean
    public ResourceServerTokenServices tokenService() {
        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
        RemoteTokenServices service = new RemoteTokenServices();
        service.setCheckTokenEndpointUrl("http://localhost:8080/auth/oauth/check_token");
        //客户端id
        service.setClientId("c1");
        //客户端密钥
        service.setClientSecret("secret");
        return service;
    }

注意 service.setCheckTokenEndpointUrl(“http://localhost:8080/auth/oauth/check_token”);
要根据自己项目url来。

测试

启动 auth 服务 , 启动 order 服务

首先我们先来访问 order 服务中的 controller接口 localhost:8081/order/r/r1
在这里插入图片描述
直接报401的错误,并且提醒我们:Full authentication is required to access this resourceFull authentication is required to access this resource(访问此资源需要完全身份验证)

因为我们刚才访问的时候没有携带token,所以平台A就不能拿到张三的个人信息,平台A只能去申请令牌,才能继续访问。

上一篇文章中 auth 认证授权服务 已经写完认证授权功能,这里为了演示方便,我就不采取客户端模式,直接用密码模式来演示。

申请令牌
在这里插入图片描述
响应结果

{
    "access_token": "148ec1b5-26ce-4b0a-89d0-45fd6155a7a5",
    "token_type": "bearer",
    "refresh_token": "a5c199ca-3caf-45a0-85f1-9e43040a8f10",
    "expires_in": 39859,
    "scope": "all"
}

请求资源
按照oauth2.0协议要求,请求资源需要携带token,如下:
token的参数名称为:Authorization,值为:Bearer access_token值。

注意:在写,Bearer access_token 的时候中间是有一个空格的,
并且请求的参数是放在 headers 里面。
在这里插入图片描述
如果token错误(少写一个5),则授权失败,如下:
在这里插入图片描述

接着测试

修改centroller中的方法,添加一个权限 @PreAuthorize(“hasAnyAuthority(‘p2’)”)

@RestController
@RequestMapping("/r")
public class OrderController {

    @GetMapping(value = "/r1")
    @PreAuthorize("hasAnyAuthority('p2')")
    public String r1() {
        return "张三的个人信息";
    }

}

先校验一下token,
在这里插入图片描述
响应的数据

{
    "aud": [
        "res1"
    ],
    "exp": 1612116736,
    "user_name": "zhangsan",
    "authorities": [
        "admin",
        "p1"
    ],
    "client_id": "c1",
    "scope": [
        "all"
    ]
}

我们发现 token:148ec1b5-26ce-4b0a-89d0-45fd6155a7a5 的权限是admin 和p1
但是controller中的方法是: @PreAuthorize(“hasAnyAuthority(‘p2’)”)

重启order 服务

接着访问
在这里插入图片描述

到此为止,差不多介绍完了吧
下一篇文章是在现有的基础上讲解jwt令牌

原文链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值