2012-04-03 152 views
0

我正在開發一個使用Spring Security進行用戶身份驗證的Web應用程序。 我知道,我能登錄的用戶以這種方式:哪一種獲得彈簧安全登錄用戶的最佳方式?

public class SecurityUtil { 
    public static User getCurrentUser() { 
     SecurityContextHolder.getContext().getAuthentication().getPrincipal() 
    } 
} 

並以這種方式工作得很好。 現在的問題是:哪個是訪問此值的最佳方式?我會做一些例如:

1.用戶聲明爲控制器變量:

public class FooController { 

    @Autowired 
    private FooService fooService; 

    private User u = SecurityUtil.getCurrentUser(); 

    @RequestMapping(...) 
    public void control() { 

     fooService.doSomething(u); 
    } 
} 

2.用戶作爲參數傳遞給服務:

public class FooController { 

    @Autowired 
    private FooService fooService; 

    public void control() { 

     fooService.doSomething(SecurityUtil.getCurrentUser()); 
    } 
} 

3.用戶在訪問服務:

public class FooService { 

    public void doSomething() { 

     SecurityUtil.getCurrentUser(); 
     //Do something 
    } 
} 

全都是這樣的例子有效嗎?我可以不清楚地使用它們中的任何一個嗎?我應該知道哪些缺點?

+0

您使用的是哪個版本的Spring? – 2012-04-03 11:48:18

回答

2

實施例1

實施例1不可用,因爲彈簧豆缺省情況下爲單,這意味着所創建的FooController時,所述可變User不正確地分配,或者它是null。正如其他答案指出的那樣,它也不是線程安全的。

實施例2

實施例2是我推薦的方式做到這一點,它是在單元測試的可測試性。但我會建議使用下面的例子中(春3),參考文檔here

@RequestMapping(method = RequestMethod.GET) 
public String index(Model m, HttpSession session, Principal principal) { 
    // principal.getName() return username 
    return "XYZ"; 
} 

例3

例3是可用的,但不容易測試和難以維護。

+0

真的嗎?你的例子在Spring 3中有效嗎?我不知道......這非常優雅! – Fabio 2012-04-03 12:15:14

+0

@Fabio,是的,它在Spring 3中工作,請參閱我更新的答案,並鏈接到spring文檔 – 2012-04-03 12:22:06

0

示例1不是線程安全的。一般來說,你的服務bean應該是無狀態的。

使用示例3,它取決於您如何從控制器調用FooService。如果此調用跨越應用程序邊界,那麼您需要確保Spring SecurityContext隨調用一起傳播以使其工作。

示例二應該在所有情況下都可以,但將當前用戶傳遞給服務方法似乎不是正確的問題分離。