2016-08-30 165 views
1

我想了解spring安全性。我正在使用java-config而不是xml。我試圖創建一個控制器,然後測試@PreAuthorize表示法。但在我的給定代碼中,@PreAuthorize僅在與getActiveSessions函數一起使用時纔有效,但在與getName函數一起使用時它不起作用。所以這段代碼按預期工作@PreAuthorize不起作用從另一個函數調用的函數

public class DemoSessionController extends SessionController{ 

     @RequestMapping("/welcome/{a}") 
     @PreAuthorize("hasRole('ROLE_ADMIN')") 
     public String getActiveSessions(@PathVariable String a) { 
      // TODO Auto-generated method stub 
      String str = getName(a); 
      return str; 
     } 

     public String getName(String name) { 
      // TODO Auto-generated method stub 
      return "This is "+name+""; 
     } 
    } 

但這並不

public class DemoSessionController extends SessionController{ 

    @RequestMapping("/welcome/{a}") 
    public String getActiveSessions(@PathVariable String a) { 
     // TODO Auto-generated method stub 
     String str = getName(a); 
     return str; 
    } 

    @PreAuthorize("hasRole('ROLE_ADMIN')") 
    public String getName(String name) { 
     // TODO Auto-generated method stub 
     return "This is "+name+""; 
    } 
} 

有人能解釋爲什麼第二種情況下不工作,我怎樣才能使它發揮作用?謝謝 !!

+2

Spring使用代理申請AOP。當只使用代理方法調用INTO時,對象會通過代理,內部方法調用繞過代理。爲了使它工作,您需要一個完整的AOP解決方案,比如AspectJ,可以加載或編譯時間編碼。 –

+0

@ M.Deinum感謝您的及時和明確的答覆。我明白爲什麼現在不行。關於使它工作,你說'全面爆炸'的方式,這是否意味着解決方案會很麻煩?你能否給任何可能有幫助的資源提供鏈接?謝謝 !! – varunkr

+0

我知道它與Java配置一起工作,但我現在無法訪問我的代碼。基本上,有兩個上下文(DispatcherServlet vs其他)。如果安全配置適用於正確的(或兩者)上下文,註釋纔會起作用。搜索網絡,你會找到解決方案。一旦配置正確,它將工作。 – Codo

回答

1

正如在評論中提到的,只有在從外部調用對象時纔會處理註釋。有幾個解決方案。

您可以拆分需要註釋以在單獨對象中處理的方法,例如,一個管理對象,其註釋爲

@PreAuthorize("hasRole('ROLE_ADMIN')") 

在類級別上。這樣你就不需要註釋每種方法。您應該將該類中的內部方法標記爲private,以防止它們從外部使用。這需要對應用程序邏輯進行重新排序,但將所有管理任務放在一個對象中可能會有所幫助。

另一種解決方案顯然是爲一個方法執行的所有任務添加所需的註釋,包括由公共方法使用的方法執行的註解。

編輯1:

新增樣本的類,使提出的解決方案更清晰

public class UserSessionController extends SessionController{ 
@Inject 
private AdminFacade adminFacade; 

@RequestMapping("/welcome/{a}") 
public String getActiveSessions(@PathVariable String a) { 
    return adminFacade.getName(a); 
} 
} 

@PreAuthorize("hasRole('ROLE_ADMIN')") 
public class AdminFacade { 

public String getName(String name) { 
    return "This is "+name; 
} 
public String getDetailsForAdmin(String param) { 
    return "admin details"; 
} 
} 
+0

感謝您的回覆!但我無法理解你。你可以添加一些代碼來解釋第一種方法嗎?這種方法等同於說我需要在其他bean中使用getName()方法嗎?謝謝 !! – varunkr

+0

嘿,非常感謝編輯。你的建議確實有效。我確實嘗試過類似的方法,但它並沒有提前工作。原因是我正在做類似的事情,返回新的AdminFacade()。getName(a),但這沒有奏效。在你的情況下,你正在注入尚未初始化的AdminFacade對象。其實我有兩個疑問。 1.)爲什麼你的方法工作,我的不是。 2)爲什麼沒有adminFacade.getName(a)產生一個空指針,因爲我看不到它是如何被初始化的?請清除我的疑問,我會接受你的回答!謝謝 !! – varunkr

+0

cdi容器(在你的情況下爲spring)將創建一個AdminFacade對象,並在它看到@Inject時將其設置爲變量。手動創建對象將不起作用,因爲當調用對象上的方法時,cdi容器無法做到「神奇」,即處理其他註釋。我建議你看看CDI教程http://docs.oracle.com/javaee/6/tutorial/doc/giwhl.html如果你想知道更多的細節。 – Guenther

相關問題