溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何配置統(tǒng)一資源服務(wù)器模塊

發(fā)布時(shí)間:2021-10-12 15:18:29 來源:億速云 閱讀:172 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“如何配置統(tǒng)一資源服務(wù)器模塊”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何配置統(tǒng)一資源服務(wù)器模塊”吧!

認(rèn)證服務(wù)器改造

首先我們需要改造認(rèn)證服務(wù)器,需要認(rèn)證服務(wù)器在構(gòu)建用戶權(quán)限的時(shí)候使用的是權(quán)限標(biāo)識字段。對于代碼而言只需要 UserDetailServiceImpl#loadUserByUsername()中修改即可。

@Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
 //獲取本地用戶 SysUser sysUser = sysUserMapper.selectByUserName(userName);
 if(sysUser != null){
  //獲取當(dāng)前用戶的所有角色  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());
  //獲取所有角色的權(quán)限  List<SysPermission> permissionList = sysPermissionService.listPermissionsByRoles(roleIds);

  //基于方法攔截.只需放入用戶權(quán)限標(biāo)識即可  List<String> permissionMethodList = permissionList.stream()
    .map(SysPermission::getPermission)
    .collect(Collectors.toList());
  sysUser.setPermissions(permissionMethodList);
  //構(gòu)建oauth3的用戶  return buildUserDetails(sysUser);

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

網(wǎng)關(guān)改造

網(wǎng)關(guān)服務(wù)器不再需要進(jìn)行用戶權(quán)限校驗(yàn),所以我們需要將相關(guān)校驗(yàn)邏輯全部刪除。

@Configurationpublic class SecurityConfig {
    @Bean    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception{

        http
   .httpBasic().disable()
   .csrf().disable();

        return http.build();
    }
}

獨(dú)立資源服務(wù)器配置模塊

完成了上面兩步后就到了最重要的步驟了,需要建立一個(gè)獨(dú)立的資源服務(wù)器配置模塊,用于其他模塊引用。

首先我們得建立一個(gè)單獨(dú)的資源服務(wù)模塊 cloud-component-security-starter ,如下為改造后的代碼結(jié)構(gòu)圖。

如何配置統(tǒng)一資源服務(wù)器模塊


然后,要讓一個(gè)普通后端服務(wù)成為資源服務(wù)器,需要有一個(gè)配置類繼承 ResourceServerConfigurerAdapter并進(jìn)行相關(guān)配置,那在我們獨(dú)立的資源服務(wù)器模塊我們首先得創(chuàng)建一個(gè)這樣的配置類,這個(gè)比較簡單,只需從之前的模塊中拷貝一份出來。

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);
    }
  
}

現(xiàn)在有了資源服務(wù)器配置,那其他模塊如何引入這個(gè)配置類呢?

這里我們可以借助SpringBoot的Enable模塊驅(qū)動能力,通過@EnableXXX注解導(dǎo)入配置類。

我們創(chuàng)建一個(gè)自定義注解類 EnableCloudResourceServer,其他模塊通過 @EnableCloudResourceServer注解即可導(dǎo)入資源服務(wù)器配置

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@EnableResourceServer //開啟資源服務(wù)器@Import({CloudResourceServerConfigure.class, TokenStoreConfigure.class})public @interface EnableCloudResourceServer {

}

最后我們知道微服務(wù)授權(quán)是基于方法攔截,基于方法攔截我們就需要開啟 @EnableGlobalMethodSecurity,并且需要將我們自定義的權(quán)限注解功能遷移過來。所以我們再創(chuàng)建一個(gè)配置類用于配置上述功能。

@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();
    }

}

經(jīng)過上面的改造,一個(gè)獨(dú)立的資源服務(wù)器創(chuàng)建成功了,現(xiàn)在剩下的就是對微服務(wù)的改造。

微服務(wù)改造

  • 在maven中刪除原oauth3.0的相關(guān)配置,引入自定義 cloud-component-security-starter

<dependency> <groupId>com.jianzh6.cloud</groupId> <artifactId>cloud-component-security-starter</artifactId></dependency>
  • 刪除所有資源服務(wù)器相關(guān)代碼(此過程略)

     

  • 修改主啟動類,通過 @EnableCloudResourceServer引入資源服務(wù)器配置

@EnableDiscoveryClient@SpringCloudApplication@EnableCloudResourceServerpublic class AccountServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountServiceApplication.class, args);
    }
}
  • 在需要攔截的Controller方法中添加自定義權(quán)限攔截注解 @PreAuthorize("hasPrivilege('queryAccount')")
    當(dāng)然也可以使用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);
}

測試

我們訪問一個(gè)沒有權(quán)限的方法會出現(xiàn)如下錯(cuò)誤提示,表明獨(dú)立資源服務(wù)器成功配置

如何配置統(tǒng)一資源服務(wù)器模塊

{
  "status": 500,
  "message": "不允許訪問",
  "data": null,
  "success": false,
  "timestamp": 1619052359563}
提示:@PreAuthorize 注解的異常,拋出AccessDeniedException異常,不會被accessDeniedHandler捕獲,而是會被全局異常捕獲。

如果需要自定義 @PreAuthorize錯(cuò)誤異常,可以通過全局的 @RestControllerAdvice進(jìn)行異常攔截

攔截后的自定義異常如下:

如何配置統(tǒng)一資源服務(wù)器模塊

{
  "status": 2003,
  "message": "沒有權(quán)限訪問該資源",
  "data": null,
  "success": false,
  "timestamp": 1619052359563}

到此,相信大家對“如何配置統(tǒng)一資源服務(wù)器模塊”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI