您好,登錄后才能下訂單哦!
本篇內容主要講解“如何配置統一資源服務器模塊”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何配置統一資源服務器模塊”吧!
首先我們需要改造認證服務器,需要認證服務器在構建用戶權限的時候使用的是權限標識字段。對于代碼而言只需要 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}
到此,相信大家對“如何配置統一資源服務器模塊”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。