十二.SpringCloud+Security+Oauth2实现微服务授权 - 资源服务器配置

前言

Oauth2分为授权服务和资源服务,上一章节我们对AuthServer做了Oauth2的授权服务配置,这一章节我们来配置资源服务器Resource1Server


1.概述Oauth2资源服务配置

资源服务器也需要导入oauth2的依赖

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

当客户端(web端,mobile移动端)带着Token向资源服务器发起请求获取资源,资源服务器需要对请求中的Token进行校验以及对资源进行授权,如果Token校验和授权都通过即可返回相应的数据给客户端,那么,资源服务器配什么?

Oauth2提供的资源服务配置类为ResourceServerConfigurerAdapter ,它实现与ResourceServerConfigurer 接口,提供了两个configure方法,源码如下:

**
 * @author Dave Syer
 *
 */
public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer {
   @Override
   public void configure(ResourceServerSecurityConfigurer resources)
 throws Exception { }

   @Override
   public void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated();
   }
}

注意上面是源码,别乱拷贝,解释一下:

  • ResourceServerSecurityConfigurer : 第一个configure方法的参数,它是资源服务安全配置,比如Token该如何校验就是通过它来配置的
  • HttpSecurity :第二个configure方法的参数,用作WEB安全配置,在学习Security基础的时候我们就接触过他
2.资源服务器配置实战

改造 “security-resource-server” ,增加资源服务器器配置类

//资源服务配置
@Configuration
@EnableResourceServer   //开启资源服务配置
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    //配置资源id ,对应oauth_client_details表中配置的resourceIds
    //一个资源ID可以对应一个资源服务器,如果Token中不包含该资源ID就无法访问该资源服务器
    public static final String RESOURCE_ID = "res1";

    @Bean
    public TokenStore tokenStore(){
        //return new InMemoryTokenStore();
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    //JWT令牌校验工具
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        //设置JWT签名密钥。它可以是简单的MAC密钥,也可以是RSA密钥
        jwtAccessTokenConverter.setSigningKey("123");
        return jwtAccessTokenConverter;
    }
    //资源服务器安全性配置
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //资源ID,请求中的Token必须有用该资源ID的访问权限才可以访问该资源服务器
        resources.resourceId(RESOURCE_ID);
        //指定TokenStore,使用JWT校验
        resources.tokenStore(tokenStore());
        //无状态
        resources.stateless(true);
        //验证令牌的服务,令牌验证通过才允许获取资源,使用远程校验
        //resources.tokenServices(resourceServerTokenServices());
    }

    //资源服务令牌验证服务,通过远程校验令牌
    /**
    @Bean
    public ResourceServerTokenServices resourceServerTokenServices(){
        //使用远程服务请求授权服务器校验token , 即:资源服务和授权服务器不在一个主机
        RemoteTokenServices services = new RemoteTokenServices();
        //授权服务地址 , 当浏览器访问某个资源时就会调用该远程授权服务地址去校验token
        //要求请求中必须携带token
        services.setCheckTokenEndpointUrl("http://localhost:3000/oauth/check_token");
        //客户端id,对应认证服务的客户端详情配置oauth_client_details表中的clientId
        services.setClientId("webapp");
        //密钥,对应认证服务的客户端详情配置的秘钥
        services.setClientSecret("secret");
        return services;
    }
	*/
    //SpringSecurity的相关配置
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //校验scope必须为all , 对应认证服务的客户端详情配置的clientId
                .antMatchers("/**").access("#oauth2.hasScope('all')")
                //关闭跨域伪造检查
                .and().csrf().disable()
                //把session设置为无状态,意思是使用了token,那么session不再做数据的记录
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}
  • resources.tokenStore(tokenStore()) :这是在配置Token的校验方式,使用的是JwtTokenStore,JWT自校验的方式,当然这里也可以使用resources.tokenServices指定一个RemoteTokenServices 远程校验方案,这种方案的流程是当请求到达资源服务器,资源服务会带着请求中的token,向认证服务器发起远程校验(/oauth/check_token) ,可想而知性能不怎么好。

  • resources.resourceId(RESOURCE_ID):这个是配置资源服务器ID,意思是访问这个资源服务器的请求中的Token必须包含这个资源ID的访问权限

  • .antMatchers("/**").access("#oauth2.hasScope(‘all’)"):意思是Token必须拥有all的授权访问才可以访问到资源服务器

注意:这里在配置类上开启了@EnableGlobalMethodSecurity(prePostEnabled = true),因为我这里需要使用方法授权的方式指明我们的controller方法需要什么样的权限才能访问,当然也可以使用web授权的方式(回顾web授权和方法授权)

3.编写controller

controller就是具体的资源了,我们的方法使用了注解授权

@RestController
public class ResourceController {

    @RequestMapping("/employee/list")
    //这是一个测试方法,如果资源服务器对token校验通过就能够访问该资源
    @PreAuthorize("hasAnyAuthority('employee:list')")
    public String list(){
        return "您的token验证通过,已经访问到真正的资源 employee:list";
    }

    @RequestMapping("/employee/add")
    //这是一个测试方法,如果资源服务器对token校验通过就能够访问该资源
    @PreAuthorize("hasAnyAuthority('employee:add')")
    public String add(){
        return "您的token验证通过,已经访问到真正的资源 employee:add";
    }
}

该Controller作为测试返回数据,当客户端请求“oauth-resource”过来,如果Token校验成功,将会看到"您的token验证通过,已经访问到真正的资源"

注意:需要在资源服务配置类“ResourceServerConfig ”开启全局方法授权:@EnableGlobalMethodSecurity(prePostEnabled = true)

4.测试

再走一遍获取token的流程,然后带着Token访问资源服务器,请求头携带:Authorization=Bearer token值 ,如下:
在这里插入图片描述

这里我们已经成功的访问到真正的资源 , 请求资源之前,资源服务器会发送远程请求到授权服务器验证token的合法性,并且根据当前token获取权限列表,然后在进行授权,如果权限列表拥有资源(controller的方法)所需要的权限,即可访问成功 。

如果Token是无效的会出现如下信息:
在这里插入图片描述

如果Token中的权限不包含资源所需要的权限会出现如下信息:
在这里插入图片描述

5.总结资源服务器配置

资源服务器的配置不是很多,主要是配置如下内容:

  1. 通过HttpSecurity配置 #oauth2.hasScope('all') 资源服务器的授权范围
  2. 通过ResourceServerSecurityConfigurer 配置资源服务器的ResourceID
  3. 通过ResourceServerSecurityConfigurer 配置资源服务器如何校验Token,这里使用的是RemoteTokenServices 远程校验方式

那么资源服务器的执行流程是怎么样的呢?

  1. 我们请求头中带着Token向资源服务器发送请求
  2. 资源服务器收到请求,得到Token后通过jwtAccessTokenConverter转换器进行Token的转换得到Token中的认证授权信息
  3. 然后资源服务器会校验认证信息中是否拥有资源服务器配置的授权范围(Scope),资源ID(ResourceID),如果都验证通过资源服务器还会校验权限列表是否包含当前访问的资源(controller)说需要的权限
  4. 如果授权范围(Scope),资源ID(ResourceID),方法授权都校验通过就执行相关的方法返回资源

最后再配一张认证服务到资源服务器的完整流程图吧:

在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: springcloud是一个开源的微服务框架,它基于Spring Boot,并提供了一整套解决方案,用于构建分布式系统中的各个微服务。通过使用springcloud,我们可以轻松实现服务注册与发现、负载均衡、断路器、配置中心等功能,简化了微服务开发和管理的复杂度。 springboot是一个基于Spring的轻量级开发框架,它通过开箱即用的原则,提供了一种快速构建应用程序的方式。使用springboot,我们可以简化繁琐的配置,只需少量的代码即可实现一个功能完整的应用程序,并且可以方便地和其他Spring生态的框架进行集成。 OAuth2是一种授权协议,用于保护Web应用程序、移动应用程序和API的资源。通过OAuth2协议,用户可以授权第三方应用程序访问他们的资源,而无需提供他们的密码。它提供了一种安全且可扩展的机制来处理用户身份验证和授权,并且被广泛应用于各种应用程序中。 Spring Security是一个Java框架,用于提供身份验证和访问控制的功能。它可以轻松地集成到Spring应用程序中,提供了一套强大的API和安全策略,用于保护应用程序免受各种攻击,包括身份验证和授权、会话管理、密码加密等。 Redis是一种内存数据存储系统,它以键值对的形式存储数据,并支持多种数据结构,如字符串、列表、集合、有序集合等。Redis具有高速、持久化和可扩展性等特点,可用于缓存、消息队列、分布式锁等各种场景。在使用Spring框架开发时,我们可以使用Redis作为缓存层,提高应用程序的性能和响应速度。 综上所述,Spring Cloud提供了构建和管理微服务的解决方案,Spring Boot简化了应用程序的开发,OAuth2和Spring Security提供了安全和授权的功能,而Redis作为内存数据存储系统,为应用程序提供了可扩展的缓存和数据存储能力。这些技术和框架相互协作,可以帮助开发者更快速、更安全地构建分布式系统。 ### 回答2: Spring Cloud是一个用于构建分布式系统的开发工具包,它提供了多个子项目来解决分布式系统的常见问题,例如服务注册与发现、配置管理、断路器、负载均衡等。Spring Boot是用于简化Spring应用程序开发的工具,它提供了一种自动配置的方式来快速搭建和运行Spring应用。OAuth2是一个开放标准,用于授权访问特定资源,它允许用户使用某个网站的授权信息来访问其他网站上的受保护资源。Spring Security是一个全面的身份验证和授权框架,它提供了一套安全服务,用于保护Web应用程序中的资源。Redis是一个高性能的键值存储系统,它常被用作缓存、队列、消息中间件等。 结合以上几个技术,可以构建一个基于Spring Cloud的分布式系统,使用Spring Boot快速搭建各个服务,使用Spring Security进行身份验证和授权管理。而OAuth2可以用于保护系统中的资源,通过认证服务器进行用户认证和授权,使得只有授权的用户才能访问相应的资源。Spring SecurityOAuth2可以集成使用,通过Spring Security提供的权限管理功能来管理不同角色对资源的访问权限。同时,将Redis作为缓存服务器,可用于提高系统的性能和响应速度。 总之,Spring Cloud、Spring Boot、OAuth2、Spring Security和Redis等技术可以在构建分布式系统时发挥重要作用,帮助我们快速搭建实现各个功能模块,并提供高性能和安全性。 ### 回答3: Spring Cloud是一套基于Spring Boot的微服务框架,它提供了在分布式系统中构建和管理各种微服务的解决方案。它具有服务注册与发现、负载均衡、熔断、服务网关等功能,可以方便地实现微服务架构。 Spring Boot是一个用于快速开发基于Spring框架的应用程序的工具,它简化了Spring应用程序的配置和部署流程。它提供了自动化配置、内嵌服务器、开箱即用的特性,使得我们只需要关注业务逻辑的开发而不用过多关注框架的配置OAuth2是一种开放标准的授权协议,它使得用户可以通过授权的方式将与用户相关的信息共享给第三方应用程序。它使用令牌的方式进行授权,具有安全性高、可扩展性好的优点,常用于实现单点登录和授权管理。 Spring Security是一个用于在Java应用程序中提供身份验证和访问控制的框架。它可以与Spring Boot和Spring Cloud集成,提供了认证、授权、密码加密等功能,帮助我们更好地保护应用程序的安全。 Redis是一种高性能的键值存储系统,它支持多种数据结构,如字符串、列表、哈希表等。它具有高并发读写、持久化、分布式等特点,常用于缓存、消息队列、会话管理等场景。 综上所述,Spring Cloud提供了构建微服务的解决方案,Spring Boot简化了Spring应用程序的开发,OAuth2实现授权管理,Spring Security提供了身份验证和访问控制,而Redis则可以用于缓存和数据存储。这些技术的结合可以帮助我们构建安全、高效的分布式系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值