【问题标题】:Howto access HttpSession from a custom DataSource in Spring?如何在 Spring 中从自定义 DataSource 访问 HttpSession?
【发布时间】:2011-12-24 20:15:25
【问题描述】:

有没有办法在自定义数据源中从 WebApplicationContext 访问 HttpSession?我实现了一个自定义身份验证处理过滤器,它将一些信息存储在 HttpSession 中。然后,DataSource 使用此信息来获取数据库连接。

另一种选择是使用 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 的新类,它只有用户名和密码。然后将 ThreadLocal 重新创建为实用程序接口的静态最终变量:

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

ThreadLocal的值然后在filter的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一样吗?

【问题讨论】:

    标签: java spring spring-security datasource


    【解决方案1】:

    在典型的多层应用程序中,您的数据访问层不应该对 HTTP 接口等更高层有任何了解。

    我建议您使用 Spring 的 sessionrequest 范围进行调查。您可以在其中一个作用域中创建一个作用域代理 bean,将身份验证信息放入其中,然后将其注入数据源。

    【讨论】:

    • 关于使用作用域代理 bean 的任何好的资源?另外,访问 DataSource 中的 SecurityContext 是不是一种不好的做法?
    【解决方案2】:

    不要将该逻辑放在数据源中。 http 会话和数据库不应相关。

    您可以在 HandlerInterceptor 或 aspectj 中进行检查,围绕您的控制器或服务层进行检查

    【讨论】:

    • 如何使用HandlerInterceptor将认证信息传递给DataSource?身份验证过滤器将此信息存储在新创建的令牌以及 http 会话中。
    • 你不应该在数据源中使用它,就是这样。但是,您可以通过将其设置在 ThreadLocal 变量中并在数据源中读取它。但是请考虑将身份验证放在代码(拦截器)的前面,而不是在获取数据库连接时
    • @Bozho Spring 的会话和请求范围代理 bean 在幕后使用 ThreadLocal,但使用它们而不是 ThreadLocal 会使单元测试更容易一些。
    • @artbristol 同意了。但总的来说这是一个坏主意:)
    • 您是否建议在过滤器的尝试身份验证方法中创建一个 ThreadLocal ? HandlerInterceptor 将如何获取身份验证信息?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    相关资源
    最近更新 更多