SpringCloud Alibaba微服务实战三十 | 统一资源服务器配置模块

简介: SpringCloud Alibaba微服务实战三十 | 统一资源服务器配置模块

前面文章咱们对比过网关授权与微服务授权的区别,文章也提到了,如果要实现微服务授权,一般会构建一个独立的资源服务器配置模块,否则每个后端业务都需要进行资源服务器的配置,那本节内容我们就来完成此功能。

由于间隔时间较久,建议先阅读下面两篇相关文章回顾一下。

SpringCloud Alibaba微服务实战十九 - 集成RBAC授权

SpringCloud Alibaba微服务实战二十八 - 网关授权VS微服务授权

话不多说,我们直接开始代码改造。


认证服务器改造


首先我们需要改造认证服务器,需要认证服务器在构建用户权限的时候使用的是权限标识字段。对于代码而言只需要 UserDetailServiceImpl#loadUserByUsername()中修改即可。

@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
 //获取本地用户
 SysUser sysUser = sysUserMapper.selectByUserName(userName);
 if(sysUser != null){
  //获取当前用户的所有角色
  List<SysRole> roleList = sysRoleService.listRolesByUserId(sysUser.getId());
  sysUser.setRoles(roleList.stream().map(SysRole::getRoleCode).collect(Collectors.toList()));
  List<Integer> roleIds = roleList.stream().map(SysRole::getId).collect(Collectors.toList());
  //获取所有角色的权限
  List<SysPermission> permissionList = sysPermissionService.listPermissionsByRoles(roleIds);
  //基于方法拦截.只需放入用户权限标识即可
  List<String> permissionMethodList = permissionList.stream()
    .map(SysPermission::getPermission)
    .collect(Collectors.toList());
  sysUser.setPermissions(permissionMethodList);
  //构建oauth2的用户
  return buildUserDetails(sysUser);
 }else{
  throw  new UsernameNotFoundException("用户["+userName+"]不存在");
 }
}


网关改造


网关服务器不再需要进行用户权限校验,所以我们需要将相关校验逻辑全部删除。

@Configuration
public class SecurityConfig {
    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception{
        http
   .httpBasic().disable()
   .csrf().disable();
        return http.build();
    }
}


独立资源服务器配置模块


完成了上面两步后就到了最重要的步骤了,需要建立一个独立的资源服务器配置模块,用于其他模块引用。

首先我们得建立一个单独的资源服务模块 cloud-component-security-starter ,如下为改造后的代码结构图。

然后,要让一个普通后端服务成为资源服务器,需要有一个配置类继承 ResourceServerConfigurerAdapter并进行相关配置,那在我们独立的资源服务器模块我们首先得创建一个这样的配置类,这个比较简单,只需从之前的模块中拷贝一份出来。

public class CloudResourceServerConfigure extends ResourceServerConfigurerAdapter {
    private CustomAccessDeniedHandler accessDeniedHandler;
    private CustomAuthenticationEntryPoint exceptionEntryPoint;
    private TokenStore tokenStore;
    @Value("${security.oauth2.resource.id}")
    private String resourceId ;
    @Autowired(required = false)
    public void setAccessDeniedHandler(CustomAccessDeniedHandler accessDeniedHandler) {
        this.accessDeniedHandler = accessDeniedHandler;
    }
    @Autowired(required = false)
    public void setExceptionEntryPoint(CustomAuthenticationEntryPoint exceptionEntryPoint) {
        this.exceptionEntryPoint = exceptionEntryPoint;
    }
    @Autowired(required = false)
    public void setTokenStore(TokenStore tokenStore) {
        this.tokenStore = tokenStore;
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .antMatchers(
                        "/v2/api-docs/**",
                        "/swagger-resources/**",
                        "/swagger-ui.html",
                        "/webjars/**"
                ).permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        UserAuthenticationConverter userTokenConverter = new CustomUserAuthenticationConverter();
        accessTokenConverter.setUserTokenConverter(userTokenConverter);
        if (exceptionEntryPoint != null) {
            resources.authenticationEntryPoint(exceptionEntryPoint);
        }
        if (accessDeniedHandler != null) {
            resources.accessDeniedHandler(accessDeniedHandler);
        }
        resources.resourceId(resourceId).tokenStore(tokenStore);
    }
}


现在有了资源服务器配置,那其他模块如何引入这个配置类呢?

这里我们可以借助SpringBoot的Enable模块驱动能力,通过@EnableXXX注解导入配置类。

我们创建一个自定义注解类 EnableCloudResourceServer,其他模块通过 @EnableCloudResourceServer注解即可导入资源服务器配置

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableResourceServer //开启资源服务器
@Import({CloudResourceServerConfigure.class, TokenStoreConfigure.class})
public @interface EnableCloudResourceServer {
}

最后我们知道微服务授权是基于方法拦截,基于方法拦截我们就需要开启 @EnableGlobalMethodSecurity,并且需要将我们自定义的权限注解功能迁移过来。所以我们再创建一个配置类用于配置上述功能。

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CloudSecurityAutoConfigure extends GlobalMethodSecurityConfiguration {
    @Bean
    @ConditionalOnMissingBean(name = "accessDeniedHandler")
    public CustomAccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }
    @Bean
    @ConditionalOnMissingBean(name = "authenticationEntryPoint")
    public CustomAuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint();
    }
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new CustomMethodSecurityExpressionHandler();
    }
}

经过上面的改造,一个独立的资源服务器创建成功了,现在剩下的就是对微服务的改造。


微服务改造


  • 在maven中删除原oauth2.0的相关配置,引入自定义cloud-component-security-starter
<dependency>
 <groupId>com.jianzh5.cloud</groupId>
 <artifactId>cloud-component-security-starter</artifactId>
</dependency>


  • 删除所有资源服务器相关代码(此过程略)
  • 修改主启动类,通过@EnableCloudResourceServer引入资源服务器配置
@EnableDiscoveryClient
@SpringCloudApplication
@EnableCloudResourceServer
public class AccountServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountServiceApplication.class, args);
    }
}


  • 在需要拦截的Controller方法中添加自定义权限拦截注解@PreAuthorize("hasPrivilege('queryAccount')")
    当然也可以使用SpringSecurity原生注解 @PreAuthorize("hasAuthority('queryAccount')") ,两者作用一样。
@GetMapping("/account/getByCode/{accountCode}")
@PreAuthorize("hasPrivilege('queryAccount')")
//@PreAuthorize("hasAuthority('queryAccount')")
public ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode){
 AccountDTO accountDTO = accountService.selectByCode(accountCode);
 return ResultData.success(accountDTO);
}


测试


我们访问一个没有权限的方法会出现如下错误提示,表明独立资源服务器成功配置

{
  "status": 500,
  "message": "不允许访问",
  "data": null,
  "success": false,
  "timestamp": 1619052359563
}


提示:@PreAuthorize 注解的异常,抛出AccessDeniedException异常,不会被accessDeniedHandler捕获,而是会被全局异常捕获。

如果需要自定义 @PreAuthorize错误异常,可以通过全局的 @RestControllerAdvice进行异常拦截

拦截后的自定义异常如下:

{
  "status": 2003,
  "message": "没有权限访问该资源",
  "data": null,
  "success": false,
  "timestamp": 1619052359563
}



以上,希望对你有所帮助!

目录
相关文章
|
1月前
|
存储 弹性计算 人工智能
2025年阿里云企业云服务器ECS选购与配置全攻略
本文介绍了阿里云服务器的核心配置选择方法论,涵盖算力需求分析、网络与存储设计、地域部署策略三大维度。针对不同业务场景,如初创企业官网和AI模型训练平台,提供了具体配置方案。同时,详细讲解了购买操作指南及长期运维优化建议,帮助用户快速实现业务上云并确保高效运行。访问阿里云官方资源聚合平台可获取更多最新产品动态和技术支持。
|
11天前
|
负载均衡 JavaScript Linux
做网站如何选择云服务器?(一)配置篇
选择服务器需考虑网站规模、技术需求和地理位置。个人博客适合基础配置,企业官网需4核CPU、8GB内存,电商平台则需更高配置并配备负载均衡。技术上,展示型网站用PHP+MySQL,互动社区需Node.js/Python环境,视频类网站要大带宽。地理位置影响服务器选择,国内用户选腾讯云/阿里云,海外用户选AWS等。主流服务器类型包括虚拟主机(入门级)、云服务器(推荐)和物理服务器(高端需求)。云服务商普遍提供免费试用,便于评估性能。
36 1
|
26天前
|
Cloud Native Java Nacos
springcloud/springboot集成NACOS 做注册和配置中心以及nacos源码分析
通过本文,我们详细介绍了如何在 Spring Cloud 和 Spring Boot 中集成 Nacos 进行服务注册和配置管理,并对 Nacos 的源码进行了初步分析。Nacos 作为一个强大的服务注册和配置管理平台,为微服务架构提供
284 14
|
16天前
|
弹性计算
【已解决】Matomo本地SMTP配置可以发邮件,但部署到阿里云ECS就发不了邮件
在阿里云ECS上使用Matomo和PHPMailer发送邮件时遇到问题,邮件无法发出且接口调用Pending。经过排查,发现是ECS安全组未开放25/465端口,导致SMTP请求无法正常通信。解决方法为在安全组中配置并开放25/465端口,从而恢复邮件发送功能。
|
18天前
|
弹性计算 运维 Ubuntu
在阿里云ECS云服务器上安装、配置及高效使用Docker与Docker Compose
本文介绍了在阿里云ECS上使用Ubuntu系统安装和配置Docker及Docker Compose的详细步骤。通过这些工具,可以快速部署、弹性扩展和高效管理容器化应用,满足开发和运维需求。内容涵盖Docker的安装、镜像源配置、创建Web程序镜像以及使用Docker Compose部署WordPress等实际操作,并分享了使用体验,展示了阿里云实例的高性能和稳定性。
205 4
|
1月前
|
存储 人工智能 缓存
怎么根据自己的业务选择阿里云服务器配置大小?
本文指导如何根据业务需求精准选择阿里云服务器配置,涵盖个人轻量级至企业级、计算密集型等场景,推荐不同实例类型、存储与带宽方案,并提供成本优化策略,如包年包月节省成本、按需升级配置及选用性价比高的自研ARM架构实例。帮助用户在数字化转型中实现性能与成本的平衡。 注:以上配置与价格基于阿里云2025年官方数据,实际信息可能有所调整,请以官网实时页面为准。
|
1月前
|
人工智能 运维 监控
2025年阿里云服务器配置选择全攻略:CPU、内存、带宽与系统盘详解
在2025年,阿里云服务器以高性能、灵活扩展和稳定服务助力数字化转型,提供轻量应用服务器、通用型g8i实例等多样化配置,满足个人博客至企业级业务需求。针对不同场景(如计算密集型、内存密集型),推荐相应实例类型与带宽规划,强调成本优化策略,包括包年包月节省成本、ESSD云盘选择及地域部署建议。文中还提及安全设置、监控备份的重要性,并指出未来可关注第九代实例g9i支持的新技术。整体而言,阿里云致力于帮助用户实现性能与成本的最优平衡。 以上简介共计238个字符。
|
1月前
|
存储 安全 网络安全
阿里云国际站:阿里云服务器端口配置
悟空云@CloudWuKong阿里云是全球领先的云计算服务提供商,为用户提供弹性计算、数据库、存储、网络安全等一系列云计算服务。在使用阿里云服务器时,合理配置端口非常重要,可以提高服务器安全性和稳定性。
|
1月前
|
存储 人工智能 监控
新手小白购买阿里云服务器省钱策略、配置选型与注意事项
针对初次使用阿里云服务器的用户,本文提供系统化的指导方案以优化成本并满足业务需求。首先介绍配置选型,包括实例类型(通用型、计算型、内存型)与基础配置建议;其次阐述省钱策略,如企业认证、合理选择计费模式及批量购买;最后提醒注意事项,涵盖带宽存储规划、地域网络优化及安全管理。新手可通过明确需求、选择配置、优化购买和持续监控四步快速上手,实现高效稳定的云端部署。 注:推荐配置基于2025年阿里云产品体系,具体信息请参考官网。
|
11天前
|
Windows
Windows系统云服务器配置多用户登录
本教程介绍了在Windows云服务器上配置远程桌面服务的详细步骤,包括安装桌面会话主机和远程桌面授权、允许多用户远程连接以及配置新用户并加入远程桌面用户组。通过添加角色和功能、设置组策略以及管理用户权限,实现多用户同时登录和远程访问。按照指引操作,可顺利完成服务器的远程访问配置,提升管理和使用效率。
30 0

热门文章

最新文章