6

API中的主要數據信息和信息鏈接到項目(實體), 密碼流的好方法是:管理與項目鏈接的特定權限彈簧安全和OAuth2?Oauth2 /特定實體的密碼流/檢查權限

在這個程序,你得5微服務

  • UAA的microService:授權服務器
  • 目錄的microService
  • 訂購的microService
  • 發票的microService
  • 客戶的microService

變焦權限:

UUAMICROSERVICE

每個用戶都可以有很多項目,可以爲每個項目的權限:

  • CAN_MANAGE_CATALOG
  • CAN_VIEW_CATALOG
  • CAN_MANAGE_ORDER
  • CAN_VIEW_ORDER
  • CAN_MANAGE_INVOICE
  • CAN_VIEW_INVOICE
  • ...

我有很多想法,但我不知道我有沒有好辦法:

使用例:我想securise端點:

http://catalog-service/{project_key}/catalogs 

只有具有項目{project_key}的權限VIEW_CATALOG或MANAGE_CATALOG的USER纔可以列出所有當前目錄中的項目

我最初的想法:USE ProjectAccessExpression與預授權

CatalogController.java

@Controller 
public class CatalogController { 
    @PreAuthorize("@projectAccessExpression.hasPermission(#projectKey, 'manageCatalog', principal)" + 
     " or @projectAccessExpression.hasPermission(#projectKey, 'viewCatalog', principal)") 
    @RequestMapping(
      value = "/{projectKey}/catalogs", 
      method = RequestMethod.GET, 
      produces = MediaType.APPLICATION_JSON_VALUE 
    ) 
    public @ResponseBody List<Catalog> findByProject(@PathVariable("projectKey") String projectKey) { 
     return catalogService.find(); 
    } 
} 

ProjectAccessExpression。java的

@Component 
public class ProjectAccessExpression { 

     private RestTemplate restTemplate; 
     public boolean havePermission(String projectKey, String permission , String username) { 
      Boolean havePermission = restTemplate.getForObject(String.format("http://uaa-service/permission/check?project=%1&permission=%2&username=%3", 
        projectKey, permission, username 
        ), Boolean.class); 
      return havePermission; 
     } 
} 

的不便:是需要調用UAA服務每次

二想法:USE USER_ROLE

隨着USER_ROLE

  • 用戶名|角色
  • mylogin1 | SHOP1 .CAN_MANAGE_CATALOG
  • mylogin1 | SHOP1 .CAN_VIEW_CATALOG
  • mylogin1 | SHOP2 .CAN_MANAGE_CATALOG
  • mylogin1 | SHOP2 .CAN_VIEW_CATALOG
  • mylogin1 | SHOP2 .CAN_MANAGE_ORDER
  • mylogin1 | SHOP2 .CAN_VIEW_ORDER
  • ...

SHOP1SHOP2是projectKey

的不便:我不知道,但如果用戶更改權限,我需要撤銷所有令牌關聯

第三個想法:在認證blob中添加特定權限

我不知道如何爲存儲做...

並在控制器中的註釋:

@PreAuthorize("@ProjectAccessExpression.hasPermission(authentication, 'manageCatalog||viewCatalog', #projectKey) 

的不便:同樣不方便在第二個想法

回答

0

這種解決方案我使用和工作細

** 1 - 加載業務邏輯時,安全的用戶登錄**

這個例子找到用戶與角色堅持數據庫,並添加所有的角色取決於項目。手術後,我有身份驗證令牌 的GrantedAuthority:ROLE_USER,ROLE_MANAGE_CATALOG:PROJECT1,ROLE_VIEW_PROFILE:PROJECT1,ROLE_MANAGE_PROJECT:項目2,...

@Service 
public class CustomUserDetailsService implements UserDetailsService { 
@Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     Optional<User> user = userService.findByLogin(username); 

     if (!user.isPresent()) { 
      Object args[] = {username}; 
      throw new UsernameNotFoundException(
      messageSource.getMessage("user.notexist", args, "User {0} doesn't not exist", LocaleContextHolder.getLocale()) 
      ); 
     } 
     if (!user.get().isActivated()) { 
      //throw new UserNotActivatedException(String.format("User %s was not activated!", username)); 
      Object args[] = {username}; 
      throw new UserNotActivatedException(
        messageSource.getMessage("user.notactivated", args, "User {0} was not activated", LocaleContextHolder.getLocale())); 
     } 
     //Here implement your proper logic 
     //Add busness logic security Roles 
     // eg ROLE_MANAGE_PROJECT:{project_key}, ROLE_MANAGE_CATALOG:{project_key} 
     List<Role> bRoles = projectService.getRolesForUser(username) 
     user.get().getRoles().addAll(
      bRoles 
      ); 

     UserRepositoryUserDetails userDetails = new UserRepositoryUserDetails(user.get()); 
     return userDetails; 
    } 
} 

** 2檢查安全與預授權表達**

在本例中只有用戶誰擁有此權限可以進行該操作:

  1. ROLE_ADMIN或
  2. ROLE_MANAGE_PROJECT:{PROJ ectKey}

    @PreAuthorize( 「@ oauthUserAccess.hasPermission(認證, ' 」+ Constants.PP_MANAGE_PROJECT +「',#projectKey)」) @RequestMapping( 值= 「/項目/ {projectKey}」, 方法= RequestMethod.PUT, 產生= MediaType.APPLICATION_JSON_VALUE ) 公共ResponseEntity updateProject(@PathVariable( 「projectKey」)字符串projectKey,@有效@RequestBody工程項目)

的OauthUserAccess類:

@Component("oauthUserAccess") 
public class OauthUserAccess { 

    /** 
    * Check if it is the administrator of the application IMASTER 
    * @param authentication 
    * @param projectKey 
    * @return 
    */ 
    public boolean hasAdminPermission(OAuth2Authentication authentication, String projectKey) { 
     if(authentication.getOAuth2Request().getAuthorities().contains("ROLE_ADMIN")) return true; 
     return false; 
    } 
    /** 
    * 
    * @param authentication 
    * @param permissionType 
    * @param projectKey 
    * @return 
    */ 
    public boolean hasPermission(OAuth2Authentication authentication, String permissionType, String projectKey) { 
     if (!ProjectPermissionType.exist(permissionType) || 
       projectKey.isEmpty() || 
       !projectKey.matches(Constants.PROJECT_REGEX)) 
      return false; 
     if (authentication.isClientOnly()) { 
      //TODO check scope permission 
      if(authentication.getOAuth2Request().getScope().contains(permissionType+":"+projectKey)) return true; 
     } 
     if (hasAdminPermission(authentication, projectKey)) return true; 
     String projectPermission = "ROLE_" + permissionType + ":" + projectKey; 
     String projectPermissionManage = "ROLE_" + permissionType.replace("VIEW", "MANAGE") + ":" + projectKey; 
     String manageProject = "ROLE_" + Constants.PP_MANAGE_PROJECT + ":" + projectKey; 
     Predicate<GrantedAuthority> p = r -> r.getAuthority().equals(projectPermission) || r.getAuthority().equals(projectPermissionManage) || r.getAuthority().equals(manageProject); 

     if (authentication.getAuthorities().stream().anyMatch(p)) { 
      return true; 
     }; 
     return false; 
    } 

} 

3 - 優勢/劣勢

優勢

業務邏輯允許加載僅當用戶登錄到應用程序和每一個次不那麼它是用於microService架構強大的解決方案。

缺點

需要更新認證令牌或者撤銷該令牌時權限更改其他 當你更新用戶許可,註銷和登錄所需的用戶。但是,如果沒有這種安全邏輯,你就會遇到同樣的問題,例如當用戶被禁用或啓用時。

我的解決方案我在控制器中使用,例如:

newAuthorities = projectService.getRolesForUser(username); 
UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), newAuthorities); 
     OAuth2Authentication authentication = (OAuth2Authentication)SecurityContextHolder.getContext().getAuthentication(); 
     Collection<OAuth2AccessToken> accessTokens = tokenStore.findTokensByUserName(principal.getName()); 
     OAuth2Authentication auth2 = new OAuth2Authentication(authentication.getOAuth2Request(), newAuth); 

     accessTokens.forEach(token -> { 
      if (!token.isExpired()) { 
       tokenStore.storeAccessToken(token, auth2); 
      } 
     }); 
0

基本上就像你只是試圖在您的項目中利用OAuth 2.0的角色。這裏是一些彈簧的文檔上的OAuth摘錄2.0

映射用戶角色作用域:http://projects.spring.io/spring-security-oauth/docs/oauth2.html

它有時是有用的,以限制不僅由分配給客戶端的範圍的令牌的範圍,但也根據用戶自己的權限。如果您在授權終端中使用 DefaultOAuth2RequestFactory,則可以設置標誌 checkUserScopes = true將允許的範圍限制爲僅允許與用戶角色相匹配的範圍。您也可以注入 OAuth2RequestFactory TokenEndpoint但只適用(即與密碼授權),如果您還安裝 TokenEndpointAuthenticationFilter - 你只需要HTTP BasicAuthenticationFilter一樣後添加的過濾器。當然,您也可以實現自己的規則,將範圍映射到角色,並安裝您自己的 OAuth2RequestFactory版本 AuthorizationServerEndpointsConfigurer允許您注入自定義的 OAuth2RequestFactory,因此如果您使用 @EnableAuthorizationServer,則可以使用該功能設置工廠。

所有這些基本上歸結爲您可以通過將範圍映射到您自己的自定義角色來保護具有不同範圍的端點。這樣可以讓你的安全性變得非常好。

我找到了一個不錯的步行通過,你可以作爲參考使用:(當然你必須配置設置以您自己使用的情況下)

https://raymondhlee.wordpress.com/2014/12/21/implementing-oauth2-with-spring-security/

+0

喜馬修,首先非常感謝您的回答,但我不知道你的鏈接或章節如何能幫助瞭解方法或解決此問題「將用戶角色映射到範圍」https://raymondhlee.wordpress.com/2014/12/21/implementing-oauth2-with-spring-security/。你有任何用例嗎? – timactive

+0

這裏真正的訣竅是您希望在應用程序的不同區域使用細粒度的安全性。因此,您可以爲每個應用程序區域設置自定義範圍,然後將不同的用戶角色映射到不同的範圍。這將爲您提供非常細緻的控制,因爲您可以設置基本無限級別的組合,並將它們應用於不同的應用領域。 「實施你自己的規則,將範圍映射到角色」 –

+0

好吧馬修,我認爲這只是一個基本的方案,這個例子沒有說明如何根據我的問題動態地定義一個特定的授權。示例ROLE_MANAGEPRODUCT_ {PROJECTKEY},項目鍵由用戶創建。 – timactive