2017-03-01 41 views
2

我有一個問題在我的應用程序中實現安全性... 我有自定義身份驗證並使用@PreAuthorize來處理我的用戶授權。這工作正常。現在我想實現訪問控制每個用戶,這意味着我的應用程序時,兩個用戶,「管理員」和「約翰」,可以調用方法最佳實現'訪問'用戶在春季安全

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(@PathVariable long id) { 
    return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); 
} 

「管理員」可以使用此方法對所有學生的實例,但'約翰'只能看到他的同學! 所有的用戶都可以調用這個方法(@PreAuthorize不適合),但是他們的訪問是有限的。 現在有一般方法嗎?

ACL是最好的方式?(有最好的例子嗎?)

HDIV框架可以幫助我解決我的問題?

什麼是最佳解決方案???

回答

1

分別將兩個不同的角色分配給Admin和John ROLE_ADMIN,ROLE_USER。然後檢查控制器中的角色,並調用相應的服務方法根據角色返回數據。

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(HttpServletRequest request, Authentication authentication, @PathVariable long id) { 

    if (request.isUserInRole("ROLE_ADMIN")) { 
     return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); //return all records 
    } if (request.isUserInRole("ROLE_USER")) { 
    String username = authentication.getName(); //get logged in user i.e. john 
     return ModelMapper.map(iStudentService.loadByEntityId(id, username), StudentViewModel.class); //return records by username 
    } 
} 
+0

感謝您的關注!我應該爲所有學生創造許多角色....這是最好的解決方案!!? –

1

你想看看@PostFilter@PreFilter。他們的工作方式非常類似於@PreAuthorize,但可以從列表中刪除結果。假設您還沒有這樣做,您還需要爲用戶分配不同的角色。

全局規則,像管理員能夠看到的一切,你可以通過編寫具體的實現PermissionEvaluator來實現。然後您將其添加到MethodSecurityExpressionHandler

一個簡單示例的時間。

此代碼是用文本編輯器編寫的。它可能無法編譯,並且只在這裏表現得非常簡單需要

一個步驟PermissionEvaluator

public class MyPermissionEvaluator implements PermissionEvaluator { 
    private static final SimpleGrantedAuthority AUTHORITY_ADMIN = new SimpleGrantedAuthority('admin'); 

    public boolean hasPermission(final Authentication authentication, final Object classId, final Object permission) { 
     boolean permissionGranted = false; 

     // admin can do anything 
     if (authentication.getAuthorities().contains(AUTHORITY_ADMIN)) { 
      permissionGranted = true; 
     } else { 
      // Check if the logged in user is in the same class 
     } 
     return permissionGranted; 
    } 

    @Override 
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, 
      Object permission) { 
     return false; 
    } 

} 

然後配置方法安全

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 

    @Bean 
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler(final PermissionEvaluator permissionEvaluator){ 
     DefaultMethodSecurityExpressionHandler securityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); 
     securityExpressionHandler.setPermissionEvaluator(permissionEvaluator); 
     return securityExpressionHandler; 
    } 

    @Bean 
    public PermissionEvaluator permissionEvaluator() { 
     return new MyPermissionEvaluator(); 
    } 
} 

現在我們可以用我們的過濾器上的方法

@PostFilter("hasPermission(filterObject.getClassId(), 'READ')") 
@Override 
public List<Student> getAll() { 
    return querySomeStudents(); 
} 

hasPermission i n @PostFilter ACL將調用MyPermissionEvaluator中的hasPermissionfilterObject指的是列表中的單個項目。無論您的代碼返回false,它都會從列表中刪除該項目。

+0

謝謝!!你的解決方案好得多,但我有問題。 「filterObject.getClassId()」工作如何?這個表現是否好?這是最好的方式來獲取所有列表而不是刪除一個?我想如果我在DB中寫這個過濾器是不行的? –

+0

'filterObject'是Spring使用內省獲得的。表現是一個非常相對的術語。我在很多地方使用它,沒有任何性能問題。我的感覺是寫出最乾淨,最容易維護的代碼,並在出現問題時解決性能問題。假設您已成功創建索引,從性能的角度來看,過濾數據庫中的數據是「更好」的。在數據庫上過濾也可以減少網絡I/O。 – Leon