温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何配置统一资源服务器模块

发布时间:2021-10-12 15:18:29 来源:亿速云 阅读:172 作者:iii 栏目:编程语言

本篇内容主要讲解“如何配置统一资源服务器模块”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何配置统一资源服务器模块”吧!

认证服务器改造

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

@Overridepublic 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);
  //构建oauth3的用户  return buildUserDetails(sysUser);

 }else{
  throw  new UsernameNotFoundException("用户["+userName+"]不存在");
 }
}

网关改造

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

@Configurationpublic 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.oauth3.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中删除原oauth3.0的相关配置,引入自定义 cloud-component-security-starter

<dependency> <groupId>com.jianzh6.cloud</groupId> <artifactId>cloud-component-security-starter</artifactId></dependency>
  • 删除所有资源服务器相关代码(此过程略)

     

  • 修改主启动类,通过 @EnableCloudResourceServer引入资源服务器配置

@EnableDiscoveryClient@SpringCloudApplication@EnableCloudResourceServerpublic 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}

到此,相信大家对“如何配置统一资源服务器模块”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI