2011-12-24 94 views
0

有沒有一種方法可以從自定義DataSource中的WebApplicationContext訪問HttpSession?我實現了一個定製的認證處理過濾器,它在HttpSession中存儲了一些信息。這個信息然後被一個DataSource用來獲得一個數據庫連接。如何從Spring中的自定義數據源訪問HttpSession?

另一個選擇是使用SecurityContextHolder獲取一個自定義的認證令牌,以包含其他屬性。我不確定這是否正確。

這是我到目前爲止有:

public class CustomDataSource extends DriverManagerDataSource implements ApplicationContextAware { 

protected Connection getConnectionFromDriverManager(String url, 
     Properties props) throws SQLException { 

    // want to use the web context to get the http session 

    // Authentication has a getAttribute(String name) method 
    SecurityContext securityContext = SecurityContextHolder.getContext(); 
    CustomAuthenticationToken authentication = (CustomAuthenticationToken) securityContext.getAuthentication(); 
    Object attribute = authentication.getAttribute("db"); 


    // create a connection object here 
    Object conn = getConnectionFromAttribute(attribute); 
    return (Connection)conn; 
} 

private WebApplicationContext context; 

@Override 
public void setApplicationContext(ApplicationContext applicationContext) 
     throws BeansException { 
    this.context = (WebApplicationContext)applicationContext;   
} 
} 

更新

我定義了一個名爲AUTHINFO的新類,其中只有用戶名和密碼。然後reated一個ThreadLocal作爲公用接口的靜態最終變量:

public interface WebUtils{ 
    public static final ThreadLocal<AuthInfo> authInfo = new ThreadLocal<AuthInfo>(); 
} 

ThreadLocal的的值然後在過濾器的attemptAuthentication方法設定現在

AuthInfo info = new AuthInfo(); 
info.setName(username); 
info.setPass(password); 

WebAttributes.authInfo.set(info); 

,在自定義數據源

protected Connection getConnectionFromDriverManager(String url, 
     Properties props) throws SQLException { 

    AuthInfo info = WebAttributes.authInfo.get(); 
    Connection conn = getConnFromAuthInfo(info); 
    return conn; 
} 

是不是這樣使用SecurityContextHolder和CustomAuthenticationToken?

回答

1

在典型的多層應用程序中,您的數據訪問層不應該具有任何更高層的知識,例如HTTP接口。

我建議你使用Spring的會話請求調查範圍。您可以在這些作用域之一中創建一個作用域代理bean,將認證信息放入其中,並將其注入到數據源中。

+0

任何好的資源有關使用範圍代理豆?另外,訪問DataSource中的SecurityContext是不好的做法嗎? – suikodian 2011-12-24 09:51:04

1

不要將該邏輯放置在數據源中。 http會話和數據庫不應該關聯。

你可以在一個HandlerInterceptor或AspectJ的支票,在你的控制器或服務層

+0

如何使用HandlerInterceptor將認證信息傳遞給DataSource?認證過濾器將這些信息存儲在新創建的令牌以及http會話中。 – suikodian 2011-12-24 09:49:27

+0

你不應該在數據源中使用它,就是這樣。不過,您可以將它設置在一個ThreadLocal變量中,並在數據源中讀取它。但是考慮在代碼(攔截器)中提前使用身份驗證,而不是在獲取數據庫連接時使用 – Bozho 2011-12-24 09:50:51

+0

@Bozho Spring的會話和請求範圍的代理bean使用下面的'ThreadLocal',但使用它們而不是'ThreadLocal'進行單元測試更容易一點。 – artbristol 2011-12-24 10:00:13

相關問題